]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12926 from keszybz/urlify-logs
authorLennart Poettering <lennart@poettering.net>
Wed, 10 Jul 2019 22:00:34 +0000 (00:00 +0200)
committerGitHub <noreply@github.com>
Wed, 10 Jul 2019 22:00:34 +0000 (00:00 +0200)
Urlify CONFIG_FILE and improve SYSTEMD_LOG_LOCATION

175 files changed:
.github/FUNDING.yml [new file with mode: 0644]
docs/var-log/README [new file with mode: 0644]
docs/var-log/README.in [deleted file]
docs/var-log/meson.build
fuzzbuzz.yaml [moved from fuzz.yaml with 100% similarity]
hwdb/60-sensor.hwdb
man/custom-entities.ent.in
man/systemd-debug-generator.xml
man/systemd.exec.xml
man/systemd.link.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/tmpfiles.d.xml
meson.build
meson_options.txt
semaphoreci/semaphore-runner.sh
src/analyze/analyze.c
src/basic/blockdev-util.c
src/basic/errno-util.h
src/basic/log.c
src/basic/memory-util.h
src/basic/time-util.c
src/basic/time-util.h
src/boot/bootctl.c
src/boot/efi/boot.c
src/boot/efi/loader-features.h [new file with mode: 0644]
src/core/execute.c
src/core/job.c
src/core/main.c
src/core/manager.c
src/core/path.c
src/core/selinux-access.c
src/core/service.c
src/core/socket.c
src/core/unit.c
src/cryptsetup/cryptsetup.c
src/debug-generator/debug-generator.c
src/fsck/fsck.c
src/import/curl-util.c
src/import/curl-util.h
src/journal-remote/journal-gatewayd.c
src/journal-remote/meson.build
src/journal/journalctl.c
src/journal/journald-server.c
src/journal/meson.build
src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/sd-dhcp6-lease.c
src/libsystemd/sd-bus/bus-error.c
src/libsystemd/sd-bus/test-bus-chat.c
src/libsystemd/sd-bus/test-bus-error.c
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-netlink/netlink-message.c
src/libsystemd/sd-netlink/netlink-socket.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/libsystemd/sd-netlink/test-netlink.c
src/login/logind-seat.c
src/login/meson.build
src/login/pam_systemd.c
src/login/pam_systemd.sym
src/network/meson.build
src/network/netdev/macsec.c
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/wireguard.c
src/network/netdev/xfrm.c [new file with mode: 0644]
src/network/netdev/xfrm.h [new file with mode: 0644]
src/network/networkd-brvlan.c
src/network/networkd-brvlan.h
src/network/networkd-dhcp-common.c [new file with mode: 0644]
src/network/networkd-dhcp-common.h [new file with mode: 0644]
src/network/networkd-dhcp-server.c [new file with mode: 0644]
src/network/networkd-dhcp-server.h [new file with mode: 0644]
src/network/networkd-dhcp4.c
src/network/networkd-dhcp4.h [new file with mode: 0644]
src/network/networkd-dhcp6.c
src/network/networkd-dhcp6.h [new file with mode: 0644]
src/network/networkd-ipv4ll.c
src/network/networkd-ipv4ll.h [new file with mode: 0644]
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-ndisc.c
src/network/networkd-network-bus.c
src/network/networkd-network-bus.h [new file with mode: 0644]
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-radv.c
src/network/networkd-radv.h
src/network/networkd-route.c
src/network/test-networkd-conf.c
src/nspawn/nspawn.c
src/partition/growfs.c
src/portable/portabled.c
src/reply-password/reply-password.c
src/run/run.c
src/shared/ask-password-api.c
src/shared/dissect-image.c
src/shared/dm-util.c [new file with mode: 0644]
src/shared/dm-util.h [new file with mode: 0644]
src/shared/efivars.h
src/shared/firewall-util.c
src/shared/fsck-util.h [new file with mode: 0644]
src/shared/journal-importer.c
src/shared/json.c
src/shared/meson.build
src/shared/varlink.c
src/shared/vlan-util.c
src/shared/vlan-util.h
src/systemctl/systemctl.c
src/systemd/sd-daemon.h
src/systemd/sd-netlink.h
src/test/test-alloc-util.c
src/test/test-calendarspec.c
src/test/test-path-util.c
src/test/test-sleep.c
src/test/test-strxcpyx.c
src/tmpfiles/tmpfiles.c
src/tty-ask-password-agent/tty-ask-password-agent.c
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h
test/TEST-01-BASIC/test.sh
test/TEST-02-CRYPTSETUP/test.sh
test/TEST-03-JOBS/test.sh
test/TEST-04-JOURNAL/test.sh
test/TEST-05-RLIMITS/test.sh
test/TEST-06-SELINUX/test.sh
test/TEST-07-ISSUE-1981/test.sh
test/TEST-08-ISSUE-2730/test.sh
test/TEST-09-ISSUE-2691/test.sh
test/TEST-10-ISSUE-2467/test.sh
test/TEST-11-ISSUE-3166/test.sh
test/TEST-12-ISSUE-3171/test.sh
test/TEST-13-NSPAWN-SMOKE/test.sh
test/TEST-14-MACHINE-ID/test.sh
test/TEST-16-EXTEND-TIMEOUT/test.sh
test/TEST-17-UDEV-WANTS/test.sh
test/TEST-18-FAILUREACTION/test.sh
test/TEST-19-DELEGATE/test.sh
test/TEST-20-MAINPIDGAMES/test.sh
test/TEST-23-TYPE-EXEC/test.sh
test/TEST-24-UNIT-TESTS/test.sh
test/TEST-25-IMPORT/test.sh
test/TEST-26-SETENV/test.sh
test/TEST-27-STDOUTFILE/test.sh
test/TEST-28-PERCENTJ-WANTEDBY/test.sh
test/TEST-29-UDEV-ID_RENAMING/test.sh
test/TEST-30-ONCLOCKCHANGE/test.sh
test/TEST-31-DEVICE-ENUMERATION/test.sh
test/TEST-32-OOMPOLICY/test.sh
test/TEST-34-DYNAMICUSERMIGRATE/test.sh
test/fuzz/fuzz-link-parser/directives.link
test/fuzz/fuzz-netdev-parser/27-xfrm.netdev [new file with mode: 0644]
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/27-xfrm.network [new file with mode: 0644]
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-network-parser/oss-fuzz-15678 [new file with mode: 0644]
test/test-functions
test/test-network/conf/13-not-match-udev-property.network [new file with mode: 0644]
test/test-network/conf/14-match-udev-property.network [new file with mode: 0644]
test/test-network/conf/26-bridge-vlan-master.network [new file with mode: 0644]
test/test-network/conf/26-bridge-vlan-slave.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-use-routes-no.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-with-static-address.network [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py
test/udev-test.pl
travis-ci/managers/fuzzbuzz.sh
travis-ci/managers/xenial.sh
units/systemd-portabled.service.in

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644 (file)
index 0000000..ee3b802
--- /dev/null
@@ -0,0 +1 @@
+custom: ['https://spi-inc.org/projects/systemd/', 'https://www.paypal.com/donate/?token=fBGzXDOyIGobZH3oEhYQlYlA61OMRXVnF9XXQqNNehRs-nliAU5XxozIh9z-hlmE-xXC-m']
diff --git a/docs/var-log/README b/docs/var-log/README
new file mode 100644 (file)
index 0000000..5c6c592
--- /dev/null
@@ -0,0 +1,25 @@
+You are looking for the traditional text log files in /var/log, and they are
+gone?
+
+Here's an explanation on what's going on:
+
+You are running a systemd-based OS where traditional syslog has been replaced
+with the Journal. The journal stores the same (and more) information as classic
+syslog. To make use of the journal and access the collected log data simply
+invoke "journalctl", which will output the logs in the identical text-based
+format the syslog files in /var/log used to be. For further details, please
+refer to journalctl(1).
+
+Alternatively, consider installing one of the traditional syslog
+implementations available for your distribution, which will generate the
+classic log files for you. Syslog implementations such as syslog-ng or rsyslog
+may be installed side-by-side with the journal and will continue to function
+the way they always did.
+
+Thank you!
+
+Further reading:
+        man:journalctl(1)
+        man:systemd-journald.service(8)
+        man:journald.conf(5)
+        http://0pointer.de/blog/projects/the-journal.html
diff --git a/docs/var-log/README.in b/docs/var-log/README.in
deleted file mode 100644 (file)
index 2e64fb1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-You are looking for the traditional text log files in @VARLOGDIR@, and
-they are gone?
-
-Here's an explanation on what's going on:
-
-You are running a systemd-based OS where traditional syslog has been
-replaced with the Journal. The journal stores the same (and more)
-information as classic syslog. To make use of the journal and access
-the collected log data simply invoke "journalctl", which will output
-the logs in the identical text-based format the syslog files in
-@VARLOGDIR@ used to be. For further details, please refer to
-journalctl(1).
-
-Alternatively, consider installing one of the traditional syslog
-implementations available for your distribution, which will generate
-the classic log files for you. Syslog implementations such as
-syslog-ng or rsyslog may be installed side-by-side with the journal
-and will continue to function the way they always did.
-
-Thank you!
-
-Further reading:
-        man:journalctl(1)
-        man:systemd-journald.service(8)
-        man:journald.conf(5)
-        http://0pointer.de/blog/projects/the-journal.html
index 0ddff20ce56bd2bd1513103d9b78219f776cbe44..81b786543885955d5f46811f64de374b6dc9d4af 100644 (file)
@@ -1,11 +1,6 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
-file = configure_file(
-        input : 'README.in',
-        output : 'README',
-        configuration : substs)
-
-if conf.get('HAVE_SYSV_COMPAT') == 1
-        install_data(file,
-                     install_dir : varlogdir)
+if conf.get('HAVE_SYSV_COMPAT') == 1 and get_option('create-log-dirs')
+        install_data('README',
+                     install_dir : '/var/log')
 endif
similarity index 100%
rename from fuzz.yaml
rename to fuzzbuzz.yaml
index 979e96bf000c6c46f8db2b4061d4834a9592a46b..df7ad251d0708adc863e5fe1866f876872247e31 100644 (file)
@@ -116,6 +116,9 @@ sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LA*
 sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
+
 sensor:modalias:acpi:KXJ2109*:dmi:*:svnASUSTeK*:pnME176C*
  ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
 
@@ -284,6 +287,12 @@ sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnTobefilledbyO.
 sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c:*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+#########################################
+# Irbis TW90
+#########################################
+sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW90:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
+
 #########################################
 # iOTA 360
 #########################################
index e2bd44e5e785b68f84fceb7334e9b80bc2fa56ab..85805777a0d57727973802d0a26d6b7d3333ccb2 100644 (file)
@@ -8,3 +8,4 @@
 <!ENTITY CERTIFICATE_ROOT @CERTIFICATE_ROOT@>
 <!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
 <!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
+<!ENTITY DEBUGTTY @DEBUGTTY@>
index 1f9a79db82f24a7e3bc38151e605b97f6ebcea7c..305dc2ff371bb92020e90673d5426ecb88f7361f 100644 (file)
@@ -1,7 +1,10 @@
 <?xml version="1.0"?>
 <!--*-nxml-*-->
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
 <!-- SPDX-License-Identifier: LGPL-2.1+ -->
 <refentry id="systemd-debug-generator">
 
     <option>rd.systemd.debug_shell</option> option is
     specified, the debug shell service
     <literal>debug-shell.service</literal> is pulled into the boot
-    transaction. It will spawn a debug shell on tty9 during early
-    system startup. Note that the shell may also be turned on
-    persistently by enabling it with
+    transaction and a debug shell will be spawned during early boot.
+    By default, <filename>&DEBUGTTY;</filename> is used, but a specific tty can also be set,
+    either with or without the <filename>/dev/</filename> prefix.
+    Note that the shell may also be turned on persistently by enabling it with
     <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
     <command>enable</command> command.
     <option>rd.systemd.debug_shell=</option> is honored only by initial
index bacd539b152aa3b4edadcc2d96b46351b4fb9fc4..56a029a82eeb95e63d0786b501369b29013de28d 100644 (file)
@@ -972,6 +972,15 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
         configuration or lifetime guarantees, please consider using
         <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
 
+        <para>The directories defined by these options are always created under the standard paths used by systemd
+        (<filename>/var</filename>, <filename>/run</filename>, <filename>/etc</filename>, â€¦). If the service needs
+        directories in a different location, a different mechanism has to be used to create them.</para>
+
+        <para><citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> provides
+        functionality that overlaps with these options. Using these options is recommended, because the lifetime of
+        the directories is tied directly to the lifetime of the unit, and it is not necessary to ensure that the
+        <filename>tmpfiles.d</filename> configuration is executed before the unit is started.</para>
+
         <para>Example: if a system service unit has the following,
         <programlisting>RuntimeDirectory=foo/bar baz</programlisting>
         the service manager creates <filename>/run/foo</filename> (if it does not exist),
index b1be32955e5f8aeb5e2688f4c09e38378617484d..7ea9a71107bfb4f72720a43283f66d79323d04cd 100644 (file)
         <term><varname>Driver=</varname></term>
         <listitem>
           <para>A whitespace-separated list of shell-style globs matching the driver currently bound to the
-          device, as exposed by the udev property <varname>DRIVER</varname> of its parent device, or if that
+          device, as exposed by the udev property <varname>ID_NET_DRIVER</varname> of its parent device, or if that
           is not set, the driver as exposed by <command>ethtool -i</command> of the device itself.</para>
         </listitem>
       </varlistentry>
           property <varname>DEVTYPE</varname>.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Property=</varname></term>
+        <listitem>
+          <para>A whitespace-separated list of udev property name with its value after a equal
+          (<literal>=</literal>). If multiple properties are specified, the test results are ANDed.
+          If the list is prefixed with a "!", the test is inverted. If a value contains white
+          spaces, then please quote whole key and value pair. If a value contains quotation, then
+          please escape the quotation with <literal>\</literal>.</para>
+
+          <para>Example: if a .link file has the following:
+          <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting>
+          then, the .link file matches only when an interface has all the above three properties.
+          </para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>Host=</varname></term>
         <listitem>
index d083fb9a6f406e52e595052a5fc72a213292d26f..3cce776cc226b1f7f74dbcd5d826e3a86719de3a 100644 (file)
           <row><entry><varname>fou</varname></entry>
           <entry>Foo-over-UDP tunneling.</entry></row>
 
+          <row><entry><varname>xfrm</varname></entry>
+          <entry>A virtual tunnel interface like vti/vti6 but with several advantages.</entry></row>
+
         </tbody>
       </tgroup>
     </table>
     Linux Ethernet Bonding Driver HOWTO</ulink></para>
   </refsect1>
 
+  <refsect1>
+    <title>[Xfrm] Section Options</title>
+
+    <para>The <literal>[Xfrm]</literal> section accepts the following
+    keys:</para>
+
+    <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>InterfaceId=</varname></term>
+        <listitem>
+          <para>Sets the ID/key of the xfrm interface which needs to be associated with a SA/policy.
+          Can be decimal or hexadecimal, valid range is 0-0xffffffff, defaults to 0.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Independent=</varname></term>
+        <listitem>
+          <para>Takes a boolean. If set to <literal>no</literal>, the xfrm interface should have an
+          underlying device which can be used for hardware offloading. Defaults to <literal>no</literal>.
+          See <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for how to configure the underlying device.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>For more detail information see
+      <ulink url="https://lwn.net/Articles/757391">
+        Virtual xfrm interfaces</ulink></para>
+  </refsect1>
+
   <refsect1>
     <title>[VRF] Section Options</title>
     <para>The <literal>[VRF]</literal> section only applies for
@@ -2048,6 +2081,16 @@ PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=
 AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24
 Endpoint=wireguard.example.com:51820</programlisting>
     </example>
+
+    <example>
+      <title>/etc/systemd/network/27-xfrm.netdev</title>
+      <programlisting>[Xfrm]
+Name=xfrm0
+Kind=xfrm
+
+[Xfrm]
+Independent=yes</programlisting>
+    </example>
   </refsect1>
 
   <refsect1>
index bad673b44e1c54bf460d9c37d51b1cc148d95761..c48b294551be95f8cb609eb1a3ed88e8578df4e9 100644 (file)
           <listitem>
             <para>A whitespace-separated list of shell-style globs
             matching the driver currently bound to the device, as
-            exposed by the udev property <literal>DRIVER</literal>
+            exposed by the udev property <literal>ID_NET_DRIVER</literal>
             of its parent device, or if that is not set the driver
             as exposed by <literal>ethtool -i</literal> of the
             device itself. If the list is prefixed with a "!", the
             with a "!", the test is inverted.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>Property=</varname></term>
+          <listitem>
+            <para>A whitespace-separated list of udev property name with its value after a equal
+            (<literal>=</literal>). If multiple properties are specified, the test results are ANDed.
+            If the list is prefixed with a "!", the test is inverted. If a value contains white
+            spaces, then please quote whole key and value pair. If a value contains quotation, then
+            please escape the quotation with <literal>\</literal>.</para>
+
+            <para>Example: if a .network file has the following:
+            <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting>
+            then, the .network file matches only when an interface has all the above three properties.
+            </para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Host=</varname></term>
           <listitem>
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Xfrm=</varname></term>
+        <listitem>
+          <para>The name of the xfrm to create on the link. See
+            <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+            This option may be specified more than once.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>KeepConfiguration=</varname></term>
         <listitem>
@@ -2323,6 +2346,29 @@ Name=enp0s25
 MACVTAP=macvtap-test
 </programlisting>
     </example>
+
+    <example>
+      <title>A Xfrm interface with physical underlying device.</title>
+
+      <programlisting># /etc/systemd/network/27-xfrm.netdev
+[NetDev]
+Name=xfrm0
+
+[Xfrm]
+InterfaceId=7</programlisting>
+
+      <programlisting># /etc/systemd/network/27-eth0.network
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm0</programlisting>
+
+      <para>This creates a <literal>xfrm0</literal> interface and binds it to the <literal>eth0</literal> device.
+      This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
+      If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
+      </para>
+    </example>
   </refsect1>
 
   <refsect1>
index 67bd1dc7243b9851e4c68b61e3daa192396b2c0e..ac6565ec93cb62a4f7aa5b8a5c20c78a7232fc71 100644 (file)
@@ -495,6 +495,14 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
       lines, when omitted or when set to <literal>-</literal>, the file ownership will not be modified. These
       parameters are ignored for <varname>x</varname>, <varname>r</varname>, <varname>R</varname>,
       <varname>L</varname>, <varname>t</varname>, and <varname>a</varname> lines.</para>
+
+      <para>This field should generally only reference system users/groups, i.e. users/groups that are
+      guaranteed to be resolvable during early boot. If this field references users/groups that only become
+      resolveable during later boot (i.e. after NIS, LDAP or a similar networked directory service become
+      available), execution of the operations declared by the line will likely fail. Also see <ulink
+      url="https://systemd.io/UIDS-GIDS.html#notes-on-resolvability-of-user-and-group-names">Notes on
+      Resolvability of User and Group Names</ulink> for more information on requirements on system user/group
+      definitions.</para>
     </refsect2>
 
     <refsect2>
index bffa9c2d3e835395f137d5bb77e8e7f4aa707809..14a56c29c8541a967f55d45db59520421f30e290 100644 (file)
@@ -117,7 +117,6 @@ pkgconfiglibdir = get_option('pkgconfiglibdir') == '' ? join_paths(libdir, 'pkgc
 polkitpolicydir = join_paths(datadir, 'polkit-1/actions')
 polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d')
 polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d')
-varlogdir = join_paths(localstatedir, 'log')
 xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d')
 rpmmacrosdir = get_option('rpmmacrosdir')
 if rpmmacrosdir != 'no'
@@ -276,7 +275,6 @@ substs.set('systemenvgeneratordir',                           systemenvgenerator
 substs.set('userenvgeneratordir',                             userenvgeneratordir)
 substs.set('systemshutdowndir',                               systemshutdowndir)
 substs.set('systemsleepdir',                                  systemsleepdir)
-substs.set('VARLOGDIR',                                       varlogdir)
 substs.set('CERTIFICATEROOT',                                 get_option('certificate-root'))
 substs.set('SYSTEMCTL',                                       join_paths(rootbindir, 'systemctl'))
 substs.set('RANDOM_SEED',                                     join_paths(randomseeddir, 'random-seed'))
@@ -793,6 +791,7 @@ conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
 
 substs.set('SUSHELL', get_option('debug-shell'))
 substs.set('DEBUGTTY', get_option('debug-tty'))
+conf.set_quoted('DEBUGTTY', get_option('debug-tty'))
 
 enable_debug_hashmap = false
 enable_debug_mmap_cache = false
@@ -1373,6 +1372,7 @@ config_h = configure_file(
 meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
 
 includes = include_directories('src/basic',
+                               'src/boot',
                                'src/shared',
                                'src/systemd',
                                'src/journal',
index e56d33760b4ae7f3be18cb19d44a50a5281b8b15..7c8a769bbc562cb5dac5eafdef901d519b16a4f4 100644 (file)
@@ -95,6 +95,8 @@ option('timesyncd', type : 'boolean',
        description : 'install the systemd-timesyncd daemon')
 option('remote', type : 'combo', choices : ['auto', 'true', 'false'],
        description : 'support for "journal over the network"')
+option('create-log-dirs', type : 'boolean',
+       description : 'create /var/log/journal{,/remote}')
 option('nss-myhostname', type : 'boolean',
        description : 'install nss-myhostname module')
 option('nss-mymachines', type : 'combo', choices : ['auto', 'true', 'false'],
index 1951dcbbada6a8e9fe6bdf33025ac99e8b8fb4ea..41454b474aea74b390de2bd724544b6fc3a63ad2 100755 (executable)
@@ -34,7 +34,7 @@ create_container() {
 sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
 # wait until online
 while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
-apt-get -q update
+apt-get -q --allow-releaseinfo-change update
 apt-get -y dist-upgrade
 apt-get install -y eatmydata
 EOF
index 40f54f9d46cf657657dbd8232466db5b3e6e50ec..97642660e49f4a2da6dafbbf7a4eba9ee8115c8c 100644 (file)
@@ -544,7 +544,7 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
         if (t->kernel_done_time > 0)
                 strpcpyf(&ptr, size, "= %s ", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
 
-        if (unit_id && activated_time > 0 && activated_time != USEC_INFINITY) {
+        if (unit_id && timestamp_is_set(activated_time)) {
                 usec_t base = t->userspace_time > 0 ? t->userspace_time : t->reverse_offset;
 
                 size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id,
index 625bbdd943435cef8a67e79cfea25983f14a759d..0ee14cbc0b2927582ef738652056b078dbd955f5 100644 (file)
@@ -21,6 +21,9 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
 
         assert(ret);
 
+        if (major(d) == 0)
+                return -ENODEV;
+
         /* If it has a queue this is good enough for us */
         xsprintf_sys_block_path(p, "/queue", d);
         if (access(p, F_OK) >= 0) {
@@ -31,7 +34,7 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
         /* If it is a partition find the originating device */
         xsprintf_sys_block_path(p, "/partition", d);
         if (access(p, F_OK) < 0)
-                return -ENOENT;
+                return -errno;
 
         /* Get parent dev_t */
         xsprintf_sys_block_path(p, "/../dev", d);
@@ -46,10 +49,10 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
         /* Only return this if it is really good enough for us. */
         xsprintf_sys_block_path(p, "/queue", devt);
         if (access(p, F_OK) < 0)
-                return -ENOENT;
+                return -errno;
 
         *ret = devt;
-        return 0;
+        return 1;
 }
 
 int get_block_device(const char *path, dev_t *dev) {
index d7a5ea771f4ffaea05efdf19094797d6fb3f1ede..3ad732b91ee2ea6ad8022491ebd1e178b5563e80 100644 (file)
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <stdlib.h>
+#include <string.h>
+
 #include "macro.h"
 
 static inline void _reset_errno_(int *saved_errno) {
@@ -28,6 +31,11 @@ static inline int negative_errno(void) {
         return -errno;
 }
 
+static inline char *strerror_safe(int error) {
+        /* 'safe' here does NOT mean thread safety. */
+        return strerror(abs(error));
+}
+
 /* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5.
  *
  * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases.  See the
index a30ffb9d8701465aa8a20c01e412c2ef6e8a103c..31ecbd1d1bdbf1852bb17bbad97b46c6b1f18ad4 100644 (file)
@@ -1116,11 +1116,11 @@ void log_parse_environment_realm(LogRealm realm) {
 
         e = getenv("SYSTEMD_LOG_COLOR");
         if (e && log_show_color_from_string(e) < 0)
-                log_warning("Failed to parse bool '%s'. Ignoring.", e);
+                log_warning("Failed to parse log color '%s'. Ignoring.", e);
 
         e = getenv("SYSTEMD_LOG_LOCATION");
         if (e && log_show_location_from_string(e) < 0)
-                log_warning("Failed to parse bool '%s'. Ignoring.", e);
+                log_warning("Failed to parse log location '%s'. Ignoring.", e);
 }
 
 LogTarget log_get_target(void) {
index 0e8957b7838ed84f45878c042b9dab963d56ff52..9cb8ac3c10fcac861a76bd67262120d8eeaa804e 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <inttypes.h>
+#include <malloc.h>
 #include <stdbool.h>
 #include <string.h>
 #include <sys/types.h>
@@ -78,6 +79,16 @@ static inline void* explicit_bzero_safe(void *p, size_t l) {
 void *explicit_bzero_safe(void *p, size_t l);
 #endif
 
+static inline void erase_and_freep(void *p) {
+        void *ptr = *(void**) p;
+
+        if (ptr) {
+                size_t l = malloc_usable_size(ptr);
+                explicit_bzero_safe(ptr, l);
+                free(ptr);
+        }
+}
+
 /* Use with _cleanup_ to erase a single 'char' when leaving scope */
 static inline void erase_char(char *p) {
         explicit_bzero_safe(p, sizeof(char));
index 8ccb4a941a7467a5dac5cf7c2bb5e6cf0cfc1f54..434159f41ced6df0bebd7ec60f708b300aba4cc8 100644 (file)
@@ -267,13 +267,12 @@ static char *format_timestamp_internal(
 
         assert(buf);
 
-        if (l <
-            3 +                  /* week day */
-            1 + 10 +             /* space and date */
-            1 + 8 +              /* space and time */
-            (us ? 1 + 6 : 0) +   /* "." and microsecond part */
-            1 + 1 +              /* space and shortest possible zone */
-            1)
+        if (l < (size_t) (3 +                  /* week day */
+                          1 + 10 +             /* space and date */
+                          1 + 8 +              /* space and time */
+                          (us ? 1 + 6 : 0) +   /* "." and microsecond part */
+                          1 + 1 +              /* space and shortest possible zone */
+                          1))
                 return NULL; /* Not enough space even for the shortest form. */
         if (t <= 0 || t == USEC_INFINITY)
                 return NULL; /* Timestamp is unset */
index a238f6914d4a662cf2c14871c11a82c1a5d75765..e3a529d9709f6f549520929385d69eb4fd881fd3 100644 (file)
@@ -81,15 +81,19 @@ triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u)
 #define TRIPLE_TIMESTAMP_HAS_CLOCK(clock)                               \
         IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
 
+static inline bool timestamp_is_set(usec_t timestamp) {
+        return timestamp > 0 && timestamp != USEC_INFINITY;
+}
+
 static inline bool dual_timestamp_is_set(const dual_timestamp *ts) {
-        return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
-                (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
+        return timestamp_is_set(ts->realtime) ||
+               timestamp_is_set(ts->monotonic);
 }
 
 static inline bool triple_timestamp_is_set(const triple_timestamp *ts) {
-        return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
-                (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
-                (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
+        return timestamp_is_set(ts->realtime) ||
+               timestamp_is_set(ts->monotonic) ||
+               timestamp_is_set(ts->boottime);
 }
 
 usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
index 368dd88f5f8fb5d64089c3bc1611b5790ceb3e00..7e64d13c7f616b9e064f27929b1eaaaaecf2d1c4 100644 (file)
@@ -1156,11 +1156,12 @@ static int verb_status(int argc, char *argv[], void *userdata) {
                         uint64_t flag;
                         const char *name;
                 } flags[] = {
-                        { EFI_LOADER_FEATURE_BOOT_COUNTING,           "Boot counting"                 },
-                        { EFI_LOADER_FEATURE_CONFIG_TIMEOUT,          "Menu timeout control"          },
-                        { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control" },
-                        { EFI_LOADER_FEATURE_ENTRY_DEFAULT,           "Default entry control"         },
-                        { EFI_LOADER_FEATURE_ENTRY_ONESHOT,           "One-shot entry control"        },
+                        { EFI_LOADER_FEATURE_BOOT_COUNTING,           "Boot counting"                  },
+                        { EFI_LOADER_FEATURE_CONFIG_TIMEOUT,          "Menu timeout control"           },
+                        { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control"  },
+                        { EFI_LOADER_FEATURE_ENTRY_DEFAULT,           "Default entry control"          },
+                        { EFI_LOADER_FEATURE_ENTRY_ONESHOT,           "One-shot entry control"         },
+                        { EFI_LOADER_FEATURE_XBOOTLDR,                "Support for XBOOTLDR partition" },
                 };
 
                 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
index 57c423bfb6d8e38c3086b098cacde8b64f28ce87..4c3b39b57a7ba6d10f1af23bf159de068bfbd844 100644 (file)
@@ -9,6 +9,7 @@
 #include "disk.h"
 #include "graphics.h"
 #include "linux.h"
+#include "loader-features.h"
 #include "measure.h"
 #include "pe.h"
 #include "shim.h"
@@ -2277,11 +2278,12 @@ static VOID config_write_entries_to_variable(Config *config) {
 
 EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
         static const UINT64 loader_features =
-                (1ULL << 0) | /* I honour the LoaderConfigTimeout variable */
-                (1ULL << 1) | /* I honour the LoaderConfigTimeoutOneShot variable */
-                (1ULL << 2) | /* I honour the LoaderEntryDefault variable */
-                (1ULL << 3) | /* I honour the LoaderEntryOneShot variable */
-                (1ULL << 4) | /* I support boot counting */
+                EFI_LOADER_FEATURE_CONFIG_TIMEOUT |
+                EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT |
+                EFI_LOADER_FEATURE_ENTRY_DEFAULT |
+                EFI_LOADER_FEATURE_ENTRY_ONESHOT |
+                EFI_LOADER_FEATURE_BOOT_COUNTING |
+                EFI_LOADER_FEATURE_XBOOTLDR |
                 0;
 
         _cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
diff --git a/src/boot/efi/loader-features.h b/src/boot/efi/loader-features.h
new file mode 100644 (file)
index 0000000..40095e2
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#ifndef UINT64_C
+#  define UINT64_C(c) (c ## ULL)
+#endif
+
+#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT          (UINT64_C(1) << 0)
+#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1)
+#define EFI_LOADER_FEATURE_ENTRY_DEFAULT           (UINT64_C(1) << 2)
+#define EFI_LOADER_FEATURE_ENTRY_ONESHOT           (UINT64_C(1) << 3)
+#define EFI_LOADER_FEATURE_BOOT_COUNTING           (UINT64_C(1) << 4)
+#define EFI_LOADER_FEATURE_XBOOTLDR                (UINT64_C(1) << 5)
index abf241aa81da46d664f44b542c19b36c2066e90a..1cbb2a83de45132a8d7a1fbeac2bfd19e0bbc879 100644 (file)
@@ -4891,7 +4891,7 @@ static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
         cmd = exec_command_line(c->argv);
         fprintf(f,
                 "%sCommand Line: %s\n",
-                prefix, cmd ? cmd : strerror(ENOMEM));
+                prefix, cmd ? cmd : strerror_safe(ENOMEM));
 
         exec_status_dump(&c->exec_status, f, prefix2);
 }
index 81f5f9cb722ae3704b06693448bf3f74a1bed5b4..df7eacfbc04b6102cd50ba2920651d3117097274 100644 (file)
@@ -1347,7 +1347,7 @@ int job_coldplug(Job *j) {
         if (j->unit->job_timeout != USEC_INFINITY)
                 timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
 
-        if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
+        if (timestamp_is_set(j->begin_running_usec))
                 timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
 
         if (timeout_time == USEC_INFINITY)
index 04a6ff6366997daaabc922aa390dbcd81194318c..f5dcfa09be1aea1e4a233ec57c72f859b57f3e67 100644 (file)
@@ -1952,7 +1952,7 @@ static int initialize_runtime(
                                 log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device);
                 }
 
-                if (arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
+                if (timestamp_is_set(arg_runtime_watchdog))
                         watchdog_set_timeout(&arg_runtime_watchdog);
         }
 
index 0c1adf2850005b0002260cb88979d06e47c846c0..4a2f07368ae766c6b789551c4804e729b97b1f01 100644 (file)
@@ -2094,13 +2094,15 @@ void manager_dump(Manager *m, FILE *f, const char *prefix) {
         assert(f);
 
         for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
-                char buf[FORMAT_TIMESTAMP_MAX];
+                const dual_timestamp *t = m->timestamps + q;
+                char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
 
-                if (dual_timestamp_is_set(m->timestamps + q))
+                if (dual_timestamp_is_set(t))
                         fprintf(f, "%sTimestamp %s: %s\n",
                                 strempty(prefix),
                                 manager_timestamp_to_string(q),
-                                format_timestamp(buf, sizeof(buf), m->timestamps[q].realtime));
+                                timestamp_is_set(t->realtime) ? format_timestamp(buf, sizeof buf, t->realtime) :
+                                                                format_timespan(buf, sizeof buf, t->monotonic, 1));
         }
 
         manager_dump_units(m, f, prefix);
@@ -2896,7 +2898,7 @@ int manager_loop(Manager *m) {
         while (m->objective == MANAGER_OK) {
                 usec_t wait_usec;
 
-                if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m))
+                if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m))
                         watchdog_ping();
 
                 if (!ratelimit_below(&rl)) {
@@ -2927,7 +2929,7 @@ int manager_loop(Manager *m) {
                         continue;
 
                 /* Sleep for half the watchdog time */
-                if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m)) {
+                if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m)) {
                         wait_usec = m->runtime_watchdog / 2;
                         if (wait_usec <= 0)
                                 wait_usec = 1;
index 5a00150e9b3096aa51f9a7c3a10a5bc58a3e3aeb..562cd352a3e57b933501c3d8e13cf31975e09f51 100644 (file)
@@ -89,7 +89,7 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
                                 break;
                         }
 
-                        r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror(-r));
+                        r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror_safe(r));
                         if (cut)
                                 *cut = tmp;
                         goto fail;
index fa57f6411444dbe659a66af33049430e42e0e339..cb136322fe1f9adae5cdfa8df37d030973b322e6 100644 (file)
@@ -17,6 +17,7 @@
 #include "alloc-util.h"
 #include "audit-fd.h"
 #include "bus-util.h"
+#include "errno-util.h"
 #include "format-util.h"
 #include "log.h"
 #include "path-util.h"
@@ -158,7 +159,7 @@ static int access_init(sd_bus_error *error) {
                 /* Return an access denied error, if we couldn't load
                  * the AVC but enforcing mode was on, or we couldn't
                  * determine whether it is one. */
-                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror(saved_errno));
+                return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror_safe(saved_errno));
         }
 
         selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
index 4b50d8d02975f45e80a61befd621db6732cf762c..a7031df48a674086caab96835220896773af01e9 100644 (file)
@@ -2530,14 +2530,16 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
                         return log_oom();
 
                 n = strlen(e);
-                if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
+                if (!GREEDY_REALLOC(args, allocated, length + 2 + n + 2))
                         return log_oom();
 
                 if (length > 0)
                         args[length++] = ' ';
 
+                args[length++] = '"';
                 memcpy(args + length, e, n);
                 length += n;
+                args[length++] = '"';
         }
 
         if (!GREEDY_REALLOC(args, allocated, length + 1))
@@ -2682,7 +2684,7 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char
         for (;;) {
                 _cleanup_free_ char *arg = NULL;
 
-                r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE);
+                r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE);
                 if (r < 0)
                         return r;
                 if (r == 0)
index b6a4290c3fc20f4a2243de48d537129652e18e95..cc3dc5973d7f9cc5025a7284c612520ebae15364 100644 (file)
@@ -782,7 +782,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
 
                         r = socket_address_print(&p->address, &k);
                         if (r < 0)
-                                t = strerror(-r);
+                                t = strerror_safe(r);
                         else
                                 t = k;
 
index 463db73ff1a118e5a7bd6d015551f188f6c952ef..210a4a1a6eb0fe14758acaddc66cecd1eb97b771 100644 (file)
@@ -1326,7 +1326,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         "%s\tMerged into: %s\n",
                         prefix, u->merged_into->id);
         else if (u->load_state == UNIT_ERROR)
-                fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
+                fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error));
 
         for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
                 fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
index a001ac75067a65b0a8232e25b0c8982330349577..02f131086bd08d9898ca3c280a74eeefcf65b869 100644 (file)
@@ -637,6 +637,11 @@ static int run(int argc, char *argv[]) {
 
         log_setup_service();
 
+        crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL);
+        if (DEBUG_LOGGING)
+                /* libcryptsetup won't even consider debug messages by default */
+                crypt_set_debug_level(CRYPT_DEBUG_ALL);
+
         umask(0022);
 
         if (streq(argv[1], "attach")) {
index 5faf8d7ddf47ea04a273b0164ccbd45c4fe7fa7c..09220dc98c7310e3c9b68482cafe39e6a0f23cba 100644 (file)
@@ -3,6 +3,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "dropin.h"
 #include "generator.h"
 #include "mkdir.h"
 #include "parse-util.h"
@@ -17,11 +18,12 @@ static const char *arg_dest = NULL;
 static char *arg_default_unit = NULL;
 static char **arg_mask = NULL;
 static char **arg_wants = NULL;
-static bool arg_debug_shell = false;
+static char *arg_debug_shell = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_default_unit, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_mask, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_wants, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_debug_shell, freep);
 
 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
         int r;
@@ -57,15 +59,16 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
                         return log_oom();
 
         } else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) {
+                const char *t = NULL;
 
-                if (value) {
-                        r = parse_boolean(value);
-                        if (r < 0)
-                                log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value);
-                        else
-                                arg_debug_shell = r;
-                } else
-                        arg_debug_shell = true;
+                r = value ? parse_boolean(value) : 1;
+                if (r < 0)
+                        t = skip_dev_prefix(value);
+                else if (r > 0)
+                        t = skip_dev_prefix(DEBUGTTY);
+
+                if (free_and_strdup(&arg_debug_shell, t) < 0)
+                        return log_oom();
 
         } else if (streq(key, "systemd.unit")) {
 
@@ -143,6 +146,23 @@ static int generate_wants_symlinks(void) {
         return r;
 }
 
+static void install_debug_shell_dropin(const char *dir) {
+        int r;
+
+        if (streq(arg_debug_shell, skip_dev_prefix(DEBUGTTY)))
+                return;
+
+        r = write_drop_in_format(dir, "debug-shell.service", 50, "tty",
+                        "[Unit]\n"
+                        "Description=Early root shell on /dev/%s FOR DEBUGGING ONLY\n"
+                        "ConditionPathExists=\n"
+                        "[Service]\n"
+                        "TTYPath=/dev/%s",
+                        arg_debug_shell, arg_debug_shell);
+        if (r < 0)
+                log_warning_errno(r, "Failed to write drop-in for debug-shell.service, ignoring: %m");
+}
+
 static int run(const char *dest, const char *dest_early, const char *dest_late) {
         int r, q;
 
@@ -156,6 +176,8 @@ static int run(const char *dest, const char *dest_early, const char *dest_late)
                 r = strv_extend(&arg_wants, "debug-shell.service");
                 if (r < 0)
                         return log_oom();
+
+                install_debug_shell_dropin(arg_dest);
         }
 
         r = generate_mask_symlinks();
index 8101f9ce95853284cf4260236dd22a06e1766d82..0a5863667c024e991cdfe6e1f2ba6b435c374ea2 100644 (file)
@@ -22,6 +22,7 @@
 #include "device-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
+#include "fsck-util.h"
 #include "main-func.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "stdio-util.h"
 #include "util.h"
 
-/* exit codes as defined in fsck(8) */
-enum {
-        FSCK_SUCCESS                 = 0,
-        FSCK_ERROR_CORRECTED         = 1 << 0,
-        FSCK_SYSTEM_SHOULD_REBOOT    = 1 << 1,
-        FSCK_ERRORS_LEFT_UNCORRECTED = 1 << 2,
-        FSCK_OPERATIONAL_ERROR       = 1 << 3,
-        FSCK_USAGE_OR_SYNTAX_ERROR   = 1 << 4,
-        FSCK_USER_CANCELLED          = 1 << 5,
-        FSCK_SHARED_LIB_ERROR        = 1 << 7,
-};
-
 static bool arg_skip = false;
 static bool arg_force = false;
 static bool arg_show_progress = false;
index febcc43ce87f224797f6a5fcac2f3a6209a90d5c..96cf696652f684ac866a06aed4c41046365f1062 100644 (file)
@@ -28,13 +28,11 @@ static void curl_glue_check_finished(CurlGlue *g) {
 
 static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
         CurlGlue *g = userdata;
-        int action, k = 0, translated_fd;
+        int action, k = 0;
 
         assert(s);
         assert(g);
 
-        translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
-
         if (FLAGS_SET(revents, EPOLLIN | EPOLLOUT))
                 action = CURL_POLL_INOUT;
         else if (revents & EPOLLIN)
@@ -44,7 +42,7 @@ static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *u
         else
                 action = 0;
 
-        if (curl_multi_socket_action(g->curl, translated_fd, action, &k) != CURLM_OK)
+        if (curl_multi_socket_action(g->curl, fd, action, &k) != CURLM_OK)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Failed to propagate IO event.");
 
@@ -53,7 +51,7 @@ static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *u
 }
 
 static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
-        sd_event_source *io;
+        sd_event_source *io = socketp;
         CurlGlue *g = userdata;
         uint32_t events = 0;
         int r;
@@ -61,21 +59,11 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
         assert(curl);
         assert(g);
 
-        io = hashmap_get(g->ios, FD_TO_PTR(s));
-
         if (action == CURL_POLL_REMOVE) {
                 if (io) {
-                        int fd;
-
-                        fd = sd_event_source_get_io_fd(io);
-                        assert(fd >= 0);
-
                         sd_event_source_disable_unref(io);
 
                         hashmap_remove(g->ios, FD_TO_PTR(s));
-                        hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
-
-                        safe_close(fd);
                 }
 
                 return 0;
@@ -87,12 +75,6 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
                 return -1;
         }
 
-        r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
-        if (r < 0) {
-                log_oom();
-                return -1;
-        }
-
         if (action == CURL_POLL_IN)
                 events = EPOLLIN;
         else if (action == CURL_POLL_OUT)
@@ -107,19 +89,10 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
                 if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
                         return -1;
         } else {
-                _cleanup_close_ int fd = -1;
-
-                /* When curl needs to remove an fd from us it closes
-                 * the fd first, and only then calls into us. This is
-                 * nasty, since we cannot pass the fd on to epoll()
-                 * anymore. Hence, duplicate the fds here, and keep a
-                 * copy for epoll which we control after use. */
-
-                fd = fcntl(s, F_DUPFD_CLOEXEC, 3);
-                if (fd < 0)
+                if (sd_event_add_io(g->event, &io, s, events, curl_glue_on_io, g) < 0)
                         return -1;
 
-                if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
+                if (curl_multi_assign(g->curl, s, io) != CURLM_OK)
                         return -1;
 
                 (void) sd_event_source_set_description(io, "curl-io");
@@ -130,16 +103,6 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
                         sd_event_source_unref(io);
                         return -1;
                 }
-
-                r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
-                if (r < 0) {
-                        log_oom();
-                        hashmap_remove(g->ios, FD_TO_PTR(s));
-                        sd_event_source_unref(io);
-                        return -1;
-                }
-
-                fd = -1;
         }
 
         return 0;
@@ -204,14 +167,6 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
                 curl_multi_cleanup(g->curl);
 
         while ((io = hashmap_steal_first(g->ios))) {
-                int fd;
-
-                fd = sd_event_source_get_io_fd(io);
-                assert(fd >= 0);
-
-                hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
-
-                safe_close(fd);
                 sd_event_source_unref(io);
         }
 
index 6a7be6421cb8abbfed325afcd6f978b666cbf7d0..fa80b233422c080b273cca422a695ce937984448 100644 (file)
@@ -16,7 +16,6 @@ struct CurlGlue {
         CURLM *curl;
         sd_event_source *timer;
         Hashmap *ios;
-        Hashmap *translate_fds;
 
         void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code);
         void *userdata;
index 734e8c7f3334e80b5a466cf21ae4fdcc8460a455..459d8e86a1c957d917dbd3eece46b1da37ac88c1 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "alloc-util.h"
 #include "bus-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "hostname-util.h"
@@ -252,7 +253,7 @@ static ssize_t request_reader_entries(
         errno = 0;
         k = fread(buf, 1, n, m->tmp);
         if (k != n) {
-                log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
+                log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
                 return MHD_CONTENT_READER_END_WITH_ERROR;
         }
 
@@ -605,7 +606,7 @@ static ssize_t request_reader_fields(
         errno = 0;
         k = fread(buf, 1, n, m->tmp);
         if (k != n) {
-                log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
+                log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
                 return MHD_CONTENT_READER_END_WITH_ERROR;
         }
 
index 2887daa4bf901562aa8a797c7a1d95b5c200f252..87b8ba6495f826ddcb730a50cb3b3f1f3fb8a025 100644 (file)
@@ -63,9 +63,11 @@ if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1
         install_data('browse.html',
                      install_dir : join_paths(pkgdatadir, 'gatewayd'))
 
-        meson.add_install_script('sh', '-c',
-                                 mkdir_p.format('/var/log/journal/remote'))
-        meson.add_install_script('sh', '-c',
-                                 '''chown 0:0 $DESTDIR/var/log/journal/remote &&
-                                    chmod 755 $DESTDIR/var/log/journal/remote || :''')
+        if get_option('create-log-dirs')
+                meson.add_install_script('sh', '-c',
+                                         mkdir_p.format('/var/log/journal/remote'))
+                meson.add_install_script('sh', '-c',
+                                         '''chown 0:0 $DESTDIR/var/log/journal/remote &&
+                                            chmod 755 $DESTDIR/var/log/journal/remote || :''')
+        endif
 endif
index 27518b636342e17847218156df2bb7ed98d5939b..c25bbc3f26537dc20f07befb75b90d6c7720379c 100644 (file)
@@ -1425,7 +1425,7 @@ static int add_boot(sd_journal *j) {
         r = get_boots(j, NULL, &boot_id, arg_boot_offset);
         assert(r <= 1);
         if (r <= 0) {
-                const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
+                const char *reason = (r == 0) ? "No such boot ID in journal" : strerror_safe(r);
 
                 if (sd_id128_is_null(arg_boot_id))
                         log_error("Data from the specified boot (%+i) is not available: %s",
index 50ccc80e87cb1df89f5593292045a1011c12ec51..ce0d9ce8c985e030255ad64ca9da81228002c009 100644 (file)
@@ -1061,7 +1061,7 @@ void server_driver_message(Server *s, pid_t object_pid, const char *message_id,
                 /* We failed to format the message. Emit a warning instead. */
                 char buf[LINE_MAX];
 
-                xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r));
+                xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror_safe(r));
 
                 n = 3;
                 iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=4");
index e03d6dc232713a35da9e60216e46d9514149f417..5796f77cac365c80c02da0ca3e2e0a1720060f4c 100644 (file)
@@ -111,20 +111,22 @@ endif
 install_data('journald.conf',
              install_dir : pkgsysconfdir)
 
-meson.add_install_script(
-        'sh', '-c',
-        mkdir_p.format('/var/log/journal'))
-meson.add_install_script(
-        'sh', '-c',
-        '''chown 0:0 $DESTDIR/var/log/journal &&
-         chmod 755 $DESTDIR/var/log/journal || :''')
-if get_option('adm-group')
+if get_option('create-log-dirs')
         meson.add_install_script(
                 'sh', '-c',
-                'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :')
-endif
-if get_option('wheel-group')
+                mkdir_p.format('/var/log/journal'))
         meson.add_install_script(
                 'sh', '-c',
-                'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :')
+                '''chown 0:0 $DESTDIR/var/log/journal &&
+                   chmod 755 $DESTDIR/var/log/journal || :''')
+        if get_option('adm-group')
+                meson.add_install_script(
+                        'sh', '-c',
+                        'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :')
+        endif
+        if get_option('wheel-group')
+                meson.add_install_script(
+                        'sh', '-c',
+                        'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :')
+        endif
 endif
index 9a1b2fba89b80b87771aea47f9d52493619014e1..1f2e5c7e65eb5c5318c41c1c7ddb1079e747494a 100644 (file)
@@ -12,6 +12,7 @@
 #include "conf-parser.h"
 #include "device-util.h"
 #include "dhcp-lease-internal.h"
+#include "env-util.h"
 #include "ether-addr-util.h"
 #include "hexdecoct.h"
 #include "log.h"
@@ -73,26 +74,66 @@ int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_
         return 0;
 }
 
-static bool net_condition_test_strv(char * const *raw_patterns,
-                                    const char *string) {
-        if (strv_isempty(raw_patterns))
+static bool net_condition_test_strv(char * const *patterns, const char *string) {
+        char * const *p;
+        bool match = false, has_positive_rule = false;
+
+        if (strv_isempty(patterns))
                 return true;
 
-        /* If the patterns begin with "!", edit it out and negate the test. */
-        if (raw_patterns[0][0] == '!') {
-                char **patterns;
-                size_t i, length;
+        STRV_FOREACH(p, patterns) {
+                const char *q = *p;
+                bool invert;
+
+                invert = *q == '!';
+                q += invert;
+
+                if (!invert)
+                        has_positive_rule = true;
+
+                if (string && fnmatch(q, string, 0) == 0) {
+                        if (invert)
+                                return false;
+                        else
+                                match = true;
+                }
+        }
+
+        return has_positive_rule ? match : true;
+}
+
+static int net_condition_test_property(char * const *match_property, sd_device *device) {
+        char * const *p;
+
+        if (strv_isempty(match_property))
+                return true;
+
+        STRV_FOREACH(p, match_property) {
+                _cleanup_free_ char *key = NULL;
+                const char *val, *dev_val;
+                bool invert, v;
+
+                invert = **p == '!';
+
+                val = strchr(*p + invert, '=');
+                if (!val)
+                        return -EINVAL;
+
+                key = strndup(*p + invert, val - *p - invert);
+                if (!key)
+                        return -ENOMEM;
+
+                val++;
 
-                length = strv_length(raw_patterns) + 1; /* Include the NULL. */
-                patterns = newa(char*, length);
-                patterns[0] = raw_patterns[0] + 1; /* Skip the "!". */
-                for (i = 1; i < length; i++)
-                        patterns[i] = raw_patterns[i];
+                v = device &&
+                        sd_device_get_property_value(device, key, &dev_val) >= 0 &&
+                        fnmatch(val, dev_val, 0) == 0;
 
-                return !string || !strv_fnmatch(patterns, string, 0);
+                if (invert ? v : !v)
+                        return false;
         }
 
-        return string && strv_fnmatch(raw_patterns, string, 0);
+        return true;
 }
 
 bool net_match_config(Set *match_mac,
@@ -100,12 +141,25 @@ bool net_match_config(Set *match_mac,
                       char * const *match_drivers,
                       char * const *match_types,
                       char * const *match_names,
+                      char * const *match_property,
+                      sd_device *device,
                       const struct ether_addr *dev_mac,
-                      const char *dev_path,
-                      const char *dev_driver,
-                      const char *dev_type,
                       const char *dev_name) {
 
+        const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
+
+        if (device) {
+                (void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
+                (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
+                (void) sd_device_get_devtype(device, &dev_type);
+
+                if (!dev_name)
+                        (void) sd_device_get_sysname(device, &dev_name);
+                if (!dev_mac &&
+                    sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
+                        dev_mac = ether_aton(mac_str);
+        }
+
         if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
                 return false;
 
@@ -121,6 +175,9 @@ bool net_match_config(Set *match_mac,
         if (!net_condition_test_strv(match_names, dev_name))
                 return false;
 
+        if (!net_condition_test_property(match_property, device))
+                return false;
+
         return true;
 }
 
@@ -164,7 +221,7 @@ int config_parse_net_condition(const char *unit,
         return 0;
 }
 
-int config_parse_ifnames(
+int config_parse_match_strv(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -176,7 +233,9 @@ int config_parse_ifnames(
                 void *data,
                 void *userdata) {
 
+        const char *p = rvalue;
         char ***sv = data;
+        bool invert;
         int r;
 
         assert(filename);
@@ -184,30 +243,154 @@ int config_parse_ifnames(
         assert(rvalue);
         assert(data);
 
+        if (isempty(rvalue)) {
+                *sv = strv_free(*sv);
+                return 0;
+        }
+
+        invert = *p == '!';
+        p += invert;
+
         for (;;) {
-                _cleanup_free_ char *word = NULL;
+                _cleanup_free_ char *word = NULL, *k = NULL;
 
-                r = extract_first_word(&rvalue, &word, NULL, 0);
+                r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+                if (r == 0)
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
                         return 0;
                 }
+
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
+                if (r < 0)
+                        return log_oom();
+        }
+}
+
+int config_parse_match_ifnames(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        const char *p = rvalue;
+        char ***sv = data;
+        bool invert;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        invert = *p == '!';
+        p += invert;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *k = NULL;
+
+                r = extract_first_word(&p, &word, NULL, 0);
                 if (r == 0)
-                        break;
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Failed to parse interface name list: %s", rvalue);
+                        return 0;
+                }
 
                 if (!ifname_valid(word)) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
-                        return 0;
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Interface name is not valid or too long, ignoring assignment: %s", word);
+                        continue;
                 }
 
-                r = strv_push(sv, word);
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
                 if (r < 0)
                         return log_oom();
-
-                word = NULL;
         }
+}
 
-        return 0;
+int config_parse_match_property(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        const char *p = rvalue;
+        char ***sv = data;
+        bool invert;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        invert = *p == '!';
+        p += invert;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *k = NULL;
+
+                r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+                if (r == 0)
+                        return 0;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid syntax, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                if (!env_assignment_is_valid(word)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid property or value, ignoring assignment: %s", word);
+                        continue;
+                }
+
+                if (invert) {
+                        k = strjoin("!", word);
+                        if (!k)
+                                return log_oom();
+                } else
+                        k = TAKE_PTR(word);
+
+                r = strv_consume(sv, TAKE_PTR(k));
+                if (r < 0)
+                        return log_oom();
+        }
 }
 
 int config_parse_ifalias(const char *unit,
index ebfb1c3c754909a086000febc25d075311fc5163..7059c8ae45843ffcc5f444a5ea9e562007578cd0 100644 (file)
@@ -19,16 +19,17 @@ bool net_match_config(Set *match_mac,
                       char * const *match_driver,
                       char * const *match_type,
                       char * const *match_name,
+                      char * const *match_property,
+                      sd_device *device,
                       const struct ether_addr *dev_mac,
-                      const char *dev_path,
-                      const char *dev_driver,
-                      const char *dev_type,
                       const char *dev_name);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
 CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
 CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
-CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
 CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
 CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
 
index b0f0f849379e622ebb825c636e30e975e5407ece..85238c21d1efc954b2a6cfff975b6953a2313e00 100644 (file)
@@ -576,7 +576,7 @@ static void client_stop(sd_dhcp_client *client, int error) {
         assert(client);
 
         if (error < 0)
-                log_dhcp_client(client, "STOPPED: %s", strerror(-error));
+                log_dhcp_client_errno(client, error, "STOPPED: %m");
         else if (error == SD_DHCP_CLIENT_EVENT_STOP)
                 log_dhcp_client(client, "STOPPED");
         else
index 8b424811ad16a97ba170aea81e7b509f93ed9e77..8aebb53c873da63c6d0e0d889070c4188718cf51 100644 (file)
@@ -205,12 +205,8 @@ int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
                                         lease->dns_count,
                                         &lease->dns_allocated);
-        if (r < 0) {
-                log_dhcp6_client(client, "Invalid DNS server option: %s",
-                                 strerror(-r));
-
-                return r;
-        }
+        if (r < 0)
+                return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
 
         lease->dns_count = r;
 
@@ -336,12 +332,8 @@ int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen)
         r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
                                         lease->ntp_count,
                                         &lease->ntp_allocated);
-        if (r < 0) {
-                log_dhcp6_client(client, "Invalid SNTP server option: %s",
-                                 strerror(-r));
-
-                return r;
-        }
+        if (r < 0)
+                return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
 
         lease->ntp_count = r;
 
index 96319645d1f70e94412d6b3ce78605e04a549bb4..386187412b786a4b45a46696a35a42332a139209 100644 (file)
@@ -577,7 +577,7 @@ const char *bus_error_message(const sd_bus_error *e, int error) {
         if (error < 0)
                 error = -error;
 
-        return strerror(error);
+        return strerror_safe(error);
 }
 
 static bool map_ok(const sd_bus_error_map *map) {
index 6181fb163e1f64399b29e158b1e22fe96244eb73..d9716ae74514f80fd83c82b41bb19c50b7093f5e 100644 (file)
@@ -12,6 +12,7 @@
 #include "bus-internal.h"
 #include "bus-match.h"
 #include "bus-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "format-util.h"
 #include "log.h"
@@ -308,7 +309,7 @@ static void* client1(void *p) {
 
         errno = 0;
         if (read(pp[0], &x, 1) <= 0) {
-                log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
+                log_error("Failed to read from pipe: %s", errno != 0 ? strerror_safe(errno) : "early read");
                 goto finish;
         }
 
index f464b5b23de42b7715489957e60ad932b6925f56..cb5d62099383582c86b6d967747915ee63117b52 100644 (file)
@@ -6,6 +6,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "errno-list.h"
+#include "errno-util.h"
 
 static void test_error(void) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
@@ -88,7 +89,7 @@ static void test_error(void) {
         assert_se(!sd_bus_error_is_set(&error));
         assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
         assert_se(streq(error.name, "System.Error.EBUSY"));
-        assert_se(streq(error.message, strerror(EBUSY)));
+        assert_se(streq(error.message, strerror_safe(EBUSY)));
         assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
         assert_se(sd_bus_error_get_errno(&error) == EBUSY);
         assert_se(sd_bus_error_is_set(&error));
index 09285c19d86b6d29047128a2be01e2ee3c0bc13b..5adbceeb0247c7a7dcdf8e9ab22df27fe0927bed 100644 (file)
@@ -23,6 +23,7 @@
 #include "signal-util.h"
 #include "string-table.h"
 #include "string-util.h"
+#include "strxcpyx.h"
 #include "time-util.h"
 
 #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
@@ -3248,15 +3249,16 @@ _public_ int sd_event_dispatch(sd_event *e) {
 }
 
 static void event_log_delays(sd_event *e) {
-        char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1];
-        unsigned i;
-        int o;
+        char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p;
+        size_t l, i;
 
-        for (i = o = 0; i < ELEMENTSOF(e->delays); i++) {
-                o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]);
+        p = b;
+        l = sizeof(b);
+        for (i = 0; i < ELEMENTSOF(e->delays); i++) {
+                l = strpcpyf(&p, l, "%u ", e->delays[i]);
                 e->delays[i] = 0;
         }
-        log_debug("Event loop iterations: %.*s", o, b);
+        log_debug("Event loop iterations: %s", b);
 }
 
 _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
index 68b232b7d42242929285ad631bfa8d0aae42fca4..78504063234a631caf91bb26a208d66f0129ce2d 100644 (file)
@@ -802,24 +802,18 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
 
 static int netlink_container_parse(sd_netlink_message *m,
                                    struct netlink_container *container,
-                                   int count,
                                    struct rtattr *rta,
                                    unsigned rt_len) {
         _cleanup_free_ struct netlink_attribute *attributes = NULL;
-
-        attributes = new0(struct netlink_attribute, count);
-        if (!attributes)
-                return -ENOMEM;
+        size_t n_allocated = 0;
 
         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
                 unsigned short type;
 
                 type = RTA_TYPE(rta);
 
-                /* if the kernel is newer than the headers we used
-                   when building, we ignore out-of-range attributes */
-                if (type >= count)
-                        continue;
+                if (!GREEDY_REALLOC0(attributes, n_allocated, type + 1))
+                        return -ENOMEM;
 
                 if (attributes[type].offset != 0)
                         log_debug("rtnl: message parse - overwriting repeated attribute");
@@ -830,7 +824,7 @@ static int netlink_container_parse(sd_netlink_message *m,
         }
 
         container->attributes = TAKE_PTR(attributes);
-        container->n_attributes = count;
+        container->n_attributes = n_allocated;
 
         return 0;
 }
@@ -911,14 +905,13 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
         r = netlink_message_read_internal(m, type_id, &container, NULL);
         if (r < 0)
                 return r;
-        else
-                size = (size_t)r;
+
+        size = (size_t)r;
 
         m->n_containers++;
 
         r = netlink_container_parse(m,
                                     &m->containers[m->n_containers],
-                                    type_system_get_count(type_system),
                                     container,
                                     size);
         if (r < 0) {
@@ -931,6 +924,36 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
         return 0;
 }
 
+int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) {
+        void *container;
+        size_t size;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
+
+        r = netlink_message_read_internal(m, type_id, &container, NULL);
+        if (r < 0)
+                return r;
+
+        size = (size_t) r;
+
+        m->n_containers++;
+
+        r = netlink_container_parse(m,
+                                    &m->containers[m->n_containers],
+                                    container,
+                                    size);
+        if (r < 0) {
+                m->n_containers--;
+                return r;
+        }
+
+        m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
+
+        return 0;
+}
+
 int sd_netlink_message_exit_container(sd_netlink_message *m) {
         assert_return(m, -EINVAL);
         assert_return(m->sealed, -EINVAL);
@@ -1015,7 +1038,6 @@ int sd_netlink_message_rewind(sd_netlink_message *m) {
 
                 r = netlink_container_parse(m,
                                             &m->containers[m->n_containers],
-                                            type_system_get_count(type_system),
                                             (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
                                             NLMSG_PAYLOAD(m->hdr, size));
                 if (r < 0)
index d1c95b260f8f91b275b623a93668f65203a28857..98edb7e2bae2be11660a3005c69607c72deb7b87 100644 (file)
@@ -392,7 +392,7 @@ int socket_read_message(sd_netlink *rtnl) {
 
                 /* check that the size matches the message type */
                 if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
-                        log_debug("sd-netlink: message larger than expected, dropping");
+                        log_debug("sd-netlink: message is shorter than expected, dropping");
                         continue;
                 }
 
index 0ac3d1664b2ded813aaa758f31e95214d6667b70..450e298f2cac605c33e52f6cd8814cfc3f88a635 100644 (file)
@@ -327,6 +327,11 @@ static const NLType rtnl_link_info_data_macsec_types[] = {
         [IFLA_MACSEC_VALIDATION]     = { .type = NETLINK_TYPE_U8 },
 };
 
+static const NLType rtnl_link_info_data_xfrm_types[] = {
+        [IFLA_XFRM_LINK]         = { .type = NETLINK_TYPE_U32 },
+        [IFLA_XFRM_IF_ID]        = { .type = NETLINK_TYPE_U32 }
+};
+
 /* these strings must match the .kind entries in the kernel */
 static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
@@ -358,6 +363,7 @@ static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_CAN] = "can",
         [NL_UNION_LINK_INFO_DATA_MACSEC] = "macsec",
         [NL_UNION_LINK_INFO_DATA_NLMON] = "nlmon",
+        [NL_UNION_LINK_INFO_DATA_XFRM] = "xfrm",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -411,6 +417,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
                                                        .types = rtnl_link_info_data_can_types },
         [NL_UNION_LINK_INFO_DATA_MACSEC] =           { .count = ELEMENTSOF(rtnl_link_info_data_macsec_types),
                                                        .types = rtnl_link_info_data_macsec_types },
+        [NL_UNION_LINK_INFO_DATA_XFRM] =             { .count = ELEMENTSOF(rtnl_link_info_data_xfrm_types),
+                                                       .types = rtnl_link_info_data_xfrm_types },
 };
 
 static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
@@ -785,9 +793,20 @@ static const NLTypeSystem genl_wireguard_type_system = {
         .types = genl_wireguard_cmds,
 };
 
+static const NLType genl_mcast_group_types[] = {
+        [CTRL_ATTR_MCAST_GRP_NAME]  = { .type = NETLINK_TYPE_STRING },
+        [CTRL_ATTR_MCAST_GRP_ID]    = { .type = NETLINK_TYPE_U32 },
+};
+
+static const NLTypeSystem genl_mcast_group_type_system = {
+        .count = ELEMENTSOF(genl_mcast_group_types),
+        .types = genl_mcast_group_types,
+};
+
 static const NLType genl_get_family_types[] = {
-        [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING },
-        [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 },
+        [CTRL_ATTR_FAMILY_NAME]  = { .type = NETLINK_TYPE_STRING },
+        [CTRL_ATTR_FAMILY_ID]    = { .type = NETLINK_TYPE_U16 },
+        [CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_mcast_group_type_system },
 };
 
 static const NLTypeSystem genl_get_family_type_system = {
index fed43ae43c09640a23f54f033c497fcc82986908..efc59a0a4bc0dbbd281276f12475a97176b49f44 100644 (file)
@@ -83,6 +83,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_CAN,
         NL_UNION_LINK_INFO_DATA_MACSEC,
         NL_UNION_LINK_INFO_DATA_NLMON,
+        NL_UNION_LINK_INFO_DATA_XFRM,
         _NL_UNION_LINK_INFO_DATA_MAX,
         _NL_UNION_LINK_INFO_DATA_INVALID = -1
 } NLUnionLinkInfoData;
index b13fa224cc4c06a94f772d4ea185e35dedcbd942..868fcd01241892a24d6f61357e098544d5a9b10a 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <net/if.h>
 #include <netinet/ether.h>
+#include <linux/genetlink.h>
 
 #include "sd-netlink.h"
 
@@ -11,6 +12,7 @@
 #include "missing.h"
 #include "netlink-util.h"
 #include "socket-util.h"
+#include "stdio-util.h"
 #include "string-util.h"
 #include "util.h"
 
@@ -507,6 +509,48 @@ static void test_message(sd_netlink *rtnl) {
         assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
 }
 
+static void test_array(void) {
+        _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+
+        assert_se(sd_genl_socket_open(&genl) >= 0);
+        assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
+
+        assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
+        for (unsigned i = 0; i < 10; i++) {
+                char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
+                uint32_t id = i + 1000;
+
+                xsprintf(name, "hoge%" PRIu32, id);
+                assert_se(sd_netlink_message_open_array(m, i + 1) >= 0);
+                assert_se(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id) >= 0);
+                assert_se(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name) >= 0);
+                assert_se(sd_netlink_message_close_container(m) >= 0);
+        }
+        assert_se(sd_netlink_message_close_container(m) >= 0);
+
+        rtnl_message_seal(m);
+        assert_se(sd_netlink_message_rewind(m) >= 0);
+
+        assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
+        for (unsigned i = 0; i < 10; i++) {
+                char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
+                const char *name;
+                uint32_t id;
+
+                assert_se(sd_netlink_message_enter_array(m, i + 1) >= 0);
+                assert_se(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id) >= 0);
+                assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name) >= 0);
+                assert_se(sd_netlink_message_exit_container(m) >= 0);
+
+                assert_se(id == i + 1000);
+                xsprintf(expected, "hoge%" PRIu32, id);
+                assert_se(streq(name, expected));
+        }
+        assert_se(sd_netlink_message_exit_container(m) >= 0);
+
+}
+
 int main(void) {
         sd_netlink *rtnl;
         sd_netlink_message *m;
@@ -524,6 +568,7 @@ int main(void) {
         test_route(rtnl);
         test_message(rtnl);
         test_container(rtnl);
+        test_array();
 
         if_loopback = (int) if_nametoindex("lo");
         assert_se(if_loopback > 0);
index dc578adf6383368d6c86330a9686a2685986aba6..c3ad5f9b5b00c6af1ea4e8cee00ce3e708b700f8 100644 (file)
@@ -9,6 +9,7 @@
 #include "sd-messages.h"
 
 #include "alloc-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
@@ -377,7 +378,7 @@ int seat_read_active_vt(Seat *s) {
 
         k = read(s->manager->console_active_fd, t, sizeof(t)-1);
         if (k <= 0) {
-                log_error("Failed to read current console: %s", k < 0 ? strerror(errno) : "EOF");
+                log_error("Failed to read current console: %s", k < 0 ? strerror_safe(errno) : "EOF");
                 return k < 0 ? -errno : -EIO;
         }
 
index 832274af7871045fb14b6bdf557b13a430920e0a..0a7d3d5440589e6e8f19931febacf88c857a1c80 100644 (file)
@@ -66,6 +66,9 @@ user_runtime_dir_sources = files('''
         user-runtime-dir.c
 '''.split())
 
+pam_systemd_sym = 'src/login/pam_systemd.sym'
+pam_systemd_c = files('pam_systemd.c')
+
 if conf.get('ENABLE_LOGIND') == 1
         logind_conf = configure_file(
                 input : 'logind.conf.in',
@@ -74,9 +77,6 @@ if conf.get('ENABLE_LOGIND') == 1
         install_data(logind_conf,
                      install_dir : pkgsysconfdir)
 
-        pam_systemd_sym = 'src/login/pam_systemd.sym'
-        pam_systemd_c = files('pam_systemd.c')
-
         install_data('org.freedesktop.login1.conf',
                      install_dir : dbuspolicydir)
         install_data('org.freedesktop.login1.service',
index cd070329f4c409a6ac6fec2353005b2b379f068c..3f762cbbc30b4d7d8c89f025bbad38c5491f0202 100644 (file)
@@ -21,6 +21,7 @@
 #include "bus-internal.h"
 #include "bus-util.h"
 #include "cgroup-util.h"
+#include "errno-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
@@ -251,7 +252,7 @@ static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, co
         if (streq(limit, "infinity")) {
                 r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1);
                 if (r < 0) {
-                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                         return r;
                 }
         } else {
@@ -259,7 +260,7 @@ static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, co
                 if (r >= 0) {
                         r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U));
                         if (r < 0) {
-                                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                                 return r;
                         }
                 } else {
@@ -267,7 +268,7 @@ static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, co
                         if (r >= 0) {
                                 r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
                                 if (r < 0) {
-                                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                                         return r;
                                 }
                         } else
@@ -290,7 +291,7 @@ static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, con
         if (r >= 0) {
                 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
                 if (r < 0) {
-                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                         return r;
                 }
         } else
@@ -310,7 +311,7 @@ static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, con
         if (r >= 0) {
                 r = sd_bus_message_append(m, "(sv)", field, "t", val);
                 if (r < 0) {
-                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                        pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                         return r;
                 }
         } else if (streq(field, "CPUWeight"))
@@ -375,7 +376,7 @@ static bool validate_runtime_directory(pam_handle_t *handle, const char *path, u
          * up properly for us. */
 
         if (lstat(path, &st) < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno));
+                pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror_safe(errno));
                 goto fail;
         }
 
@@ -549,7 +550,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         r = sd_bus_open_system(&bus);
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r));
                 return PAM_SESSION_ERR;
         }
 
@@ -574,7 +575,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                         "org.freedesktop.login1.Manager",
                         "CreateSession");
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror_safe(r));
                 return PAM_SESSION_ERR;
         }
 
@@ -593,13 +594,13 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                         remote_user,
                         remote_host);
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
                 return PAM_SESSION_ERR;
         }
 
         r = sd_bus_message_open_container(m, 'a', "(sv)");
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror_safe(r));
                 return PAM_SYSTEM_ERR;
         }
 
@@ -621,7 +622,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
 
         r = sd_bus_message_close_container(m);
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror_safe(r));
                 return PAM_SYSTEM_ERR;
         }
 
@@ -648,7 +649,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
                                 &vtnr,
                                 &existing);
         if (r < 0) {
-                pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror(-r));
+                pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror_safe(r));
                 return PAM_SESSION_ERR;
         }
 
@@ -759,7 +760,7 @@ _public_ PAM_EXTERN int pam_sm_close_session(
 
                 r = sd_bus_open_system(&bus);
                 if (r < 0) {
-                        pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
+                        pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r));
                         return PAM_SESSION_ERR;
                 }
 
index 62d5d26b04b8c09da86559f97e3a235f8b71ad2d..030a00ecb7ce85bb6b8028d6976475da3c03c26a 100644 (file)
@@ -1,11 +1,4 @@
-/***
-  SPDX-License-Identifier: LGPL-2.1+
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
 {
 global:
index 5465f9eb640d8b0d8082f5ca801ca0e284d832ab..32317c7c9f8b5ba367188141a75d7efc2dedf92d 100644 (file)
@@ -43,6 +43,8 @@ sources = files('''
         netdev/l2tp-tunnel.h
         netdev/macsec.c
         netdev/macsec.h
+        netdev/xfrm.c
+        netdev/xfrm.h
         networkd-address-label.c
         networkd-address-label.h
         networkd-address-pool.c
@@ -55,11 +57,18 @@ sources = files('''
         networkd-can.h
         networkd-conf.c
         networkd-conf.h
+        networkd-dhcp-common.c
+        networkd-dhcp-common.h
+        networkd-dhcp-server.c
+        networkd-dhcp-server.h
         networkd-dhcp4.c
+        networkd-dhcp4.h
         networkd-dhcp6.c
+        networkd-dhcp6.h
         networkd-fdb.c
         networkd-fdb.h
         networkd-ipv4ll.c
+        networkd-ipv4ll.h
         networkd-ipv6-proxy-ndp.c
         networkd-ipv6-proxy-ndp.h
         networkd-link-bus.c
@@ -80,6 +89,7 @@ sources = files('''
         networkd-radv.c
         networkd-radv.h
         networkd-network-bus.c
+        networkd-network-bus.h
         networkd-network.c
         networkd-network.h
         networkd-route.c
index a4967e817bcfe0b84472772afa3598288a946b9f..cf281e75a6d456ff512c896be5cd4d507b85a6ab 100644 (file)
@@ -718,7 +718,7 @@ int config_parse_macsec_key(
 
         _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
         _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
-        _cleanup_free_ void *p;
+        _cleanup_(erase_and_freep) void *p = NULL;
         MACsec *s = userdata;
         SecurityAssociation *dest;
         size_t l;
@@ -743,18 +743,17 @@ int config_parse_macsec_key(
 
         r = unhexmem_full(rvalue, strlen(rvalue), true, &p, &l);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to parse key. Ignoring assignment: %m");
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse key. Ignoring assignment: %m");
                 return 0;
         }
+
         if (l != 16) {
                 /* See DEFAULT_SAK_LEN in drivers/net/macsec.c */
-                explicit_bzero_safe(p, l);
-                log_syntax(unit, LOG_ERR, filename, line, 0,
-                           "Invalid key length (%zu). Ignoring assignment", l);
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid key length (%zu). Ignoring assignment", l);
                 return 0;
         }
 
+        explicit_bzero_safe(dest->key, dest->key_len);
         free_and_replace(dest->key, p);
         dest->key_len = l;
 
@@ -972,7 +971,7 @@ int config_parse_macsec_use_for_encoding(
 }
 
 static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
-        _cleanup_free_ uint8_t *key = NULL;
+        _cleanup_(erase_and_freep) uint8_t *key = NULL;
         size_t key_len;
         int r;
 
@@ -987,12 +986,10 @@ static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
                 return log_netdev_error_errno(netdev, r,
                                               "Failed to read key from '%s', ignoring: %m",
                                               sa->key_file);
-        if (key_len != 16) {
-                explicit_bzero_safe(key, key_len);
+
+        if (key_len != 16)
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
-                                              "Invalid key length (%zu bytes), ignoring: %m",
-                                              key_len);
-        }
+                                              "Invalid key length (%zu bytes), ignoring: %m", key_len);
 
         explicit_bzero_safe(sa->key, sa->key_len);
         free_and_replace(sa->key, key);
index 0cf6949968b759c7dace9f964c6a73df5c93b414..33f7b3058d5ed8dcfb3df660db17499eb8c2c657 100644 (file)
@@ -22,6 +22,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "netdev/wireguard.h"
 #include "netdev/fou-tunnel.h"
 #include "netdev/l2tp-tunnel.h"
+#include "netdev/xfrm.h"
 #include "vlan-util.h"
 %}
 struct ConfigPerfItem;
@@ -218,3 +219,5 @@ WireGuardPeer.PublicKey,                  config_parse_wireguard_public_key,
 WireGuardPeer.PresharedKey,               config_parse_wireguard_preshared_key,      0,                             0
 WireGuardPeer.PresharedKeyFile,           config_parse_wireguard_preshared_key_file, 0,                             0
 WireGuardPeer.PersistentKeepalive,        config_parse_wireguard_keepalive,          0,                             0
+Xfrm.InterfaceId,                         config_parse_uint32,                       0,                             offsetof(Xfrm, if_id)
+Xfrm.Independent,                         config_parse_bool,                         0,                             offsetof(Xfrm, independent)
index 542923760355d4cf7764c52f89395b7161cc302b..7735b455b79d57e1462a22535aae51e2308bb865 100644 (file)
@@ -29,6 +29,7 @@
 #include "netdev/vxcan.h"
 #include "netdev/vxlan.h"
 #include "netdev/wireguard.h"
+#include "netdev/xfrm.h"
 #include "netlink-util.h"
 #include "network-internal.h"
 #include "networkd-link.h"
@@ -72,6 +73,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_L2TP] = &l2tptnl_vtable,
         [NETDEV_KIND_MACSEC] = &macsec_vtable,
         [NETDEV_KIND_NLMON] = &nlmon_vtable,
+        [NETDEV_KIND_XFRM] = &xfrm_vtable,
 };
 
 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -107,6 +109,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_L2TP] = "l2tp",
         [NETDEV_KIND_MACSEC] = "macsec",
         [NETDEV_KIND_NLMON] = "nlmon",
+        [NETDEV_KIND_XFRM] = "xfrm",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -807,6 +810,9 @@ int netdev_load_one(Manager *manager, const char *filename) {
         case NETDEV_KIND_ERSPAN:
                 independent = ERSPAN(netdev)->independent;
                 break;
+        case NETDEV_KIND_XFRM:
+                independent = XFRM(netdev)->independent;
+                break;
         default:
                 break;
         }
index e8a00cd4b74ae963e2939c4daee131cdad8b4beb..732b563d67627a4d4a4fab9df45a00489c033784 100644 (file)
@@ -50,6 +50,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_L2TP,
         NETDEV_KIND_MACSEC,
         NETDEV_KIND_NLMON,
+        NETDEV_KIND_XFRM,
         _NETDEV_KIND_MAX,
         _NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
         _NETDEV_KIND_INVALID = -1
index 154ca3b7a4490c71a1692b8c91a50059ba615cd3..2e9651ccebee878a473e253ad45132136ac74152 100644 (file)
@@ -480,7 +480,7 @@ static int wireguard_decode_key_and_warn(
                 unsigned line,
                 const char *lvalue) {
 
-        _cleanup_free_ void *key = NULL;
+        _cleanup_(erase_and_freep) void *key = NULL;
         size_t len;
         int r;
 
@@ -501,12 +501,10 @@ static int wireguard_decode_key_and_warn(
         if (r < 0)
                 return log_syntax(unit, LOG_ERR, filename, line, r,
                            "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue);
-        if (len != WG_KEY_LEN) {
-                explicit_bzero_safe(key, len);
+        if (len != WG_KEY_LEN)
                 return log_syntax(unit, LOG_ERR, filename, line, 0,
                            "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.",
                            lvalue, len);
-        }
 
         memcpy(ret, key, WG_KEY_LEN);
         return 0;
@@ -894,7 +892,7 @@ static void wireguard_done(NetDev *netdev) {
 }
 
 static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_KEY_LEN]) {
-        _cleanup_free_ char *key = NULL;
+        _cleanup_(erase_and_freep) char *key = NULL;
         size_t key_len;
         int r;
 
@@ -905,17 +903,11 @@ static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_
         if (r < 0)
                 return r;
 
-        if (key_len != WG_KEY_LEN) {
-                r = -EINVAL;
-                goto finalize;
-        }
+        if (key_len != WG_KEY_LEN)
+                return -EINVAL;
 
         memcpy(dest, key, WG_KEY_LEN);
-        r = 0;
-
-finalize:
-        explicit_bzero_safe(key, key_len);
-        return r;
+        return 0;
 }
 
 static int wireguard_peer_verify(WireguardPeer *peer) {
diff --git a/src/network/netdev/xfrm.c b/src/network/netdev/xfrm.c
new file mode 100644 (file)
index 0000000..c60b0b1
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "missing_network.h"
+#include "netdev/xfrm.h"
+
+static int xfrm_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *message) {
+        int if_idx, r;
+        Xfrm *x;
+
+        assert(netdev);
+        assert(message);
+
+        x = XFRM(netdev);
+
+        if (x->independent)
+                if_idx = LOOPBACK_IFINDEX;
+        else {
+                assert(link);
+                if (link->ifindex == 0)
+                        return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ENODEV), "Could not get interface index: %m");
+                if_idx = link->ifindex;
+        }
+
+        r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, if_idx);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_LINK: %m");
+
+        r = sd_netlink_message_append_u32(message, IFLA_XFRM_IF_ID, x->if_id);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_IF_ID: %m");
+
+        return 0;
+}
+
+const NetDevVTable xfrm_vtable = {
+        .object_size = sizeof(Xfrm),
+        .sections = "Match\0NetDev\0Xfrm\0",
+        .fill_message_create = xfrm_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED
+};
diff --git a/src/network/netdev/xfrm.h b/src/network/netdev/xfrm.h
new file mode 100644 (file)
index 0000000..47355a5
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "netdev/netdev.h"
+
+typedef struct Xfrm {
+        NetDev meta;
+
+        uint32_t if_id;
+        bool independent;
+} Xfrm;
+
+DEFINE_NETDEV_CAST(XFRM, Xfrm);
+extern const NetDevVTable xfrm_vtable;
index 8f9103f1466d2a54bafa66021aea3214bb88b490..c3c5d535ac663d94e8fb486a1b278a9d9134104f 100644 (file)
 
 static bool is_bit_set(unsigned bit, uint32_t scope) {
         assert(bit < sizeof(scope)*8);
-        return scope & (1 << bit);
+        return scope & (UINT32_C(1) << bit);
 }
 
 static void set_bit(unsigned nr, uint32_t *addr) {
         if (nr < BRIDGE_VLAN_BITMAP_MAX)
-                addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
+                addr[nr / 32] |= (UINT32_C(1) << (nr % 32));
 }
 
 static int find_next_bit(int i, uint32_t x) {
@@ -44,16 +44,16 @@ static int find_next_bit(int i, uint32_t x) {
 
 static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) {
         struct bridge_vlan_info br_vlan;
-        int i, j, k, r, done, cnt;
+        int i, j, k, r, cnt;
         uint16_t begin, end;
-        bool untagged = false;
+        bool done, untagged = false;
 
         assert(link);
         assert(req);
         assert(br_vid_bitmap);
         assert(br_untagged_bitmap);
 
-        i = cnt = -1;
+        cnt = 0;
 
         begin = end = UINT16_MAX;
         for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) {
@@ -63,7 +63,7 @@ static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint
 
                 base_bit = k * 32;
                 i = -1;
-                done = 0;
+                done = false;
                 do {
                         j = find_next_bit(i, vid_map);
                         if (j > 0) {
@@ -80,7 +80,7 @@ static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint
                                         goto next;
                                 }
                         } else
-                                done = 1;
+                                done = true;
 
                         if (begin != UINT16_MAX) {
                                 cnt++;
@@ -129,9 +129,8 @@ static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint
                         i = j;
                 } while (!done);
         }
-        if (!cnt)
-                return -EINVAL;
 
+        assert(cnt > 0);
         return cnt;
 }
 
@@ -149,9 +148,9 @@ static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *lin
 
 int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-        uint16_t flags;
         sd_netlink *rtnl;
+        uint16_t flags;
+        int r;
 
         assert(link);
         assert(link->manager);
@@ -204,57 +203,15 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32
         return 0;
 }
 
-static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) {
-        int r;
-        char *p;
-        char *_rvalue = NULL;
-        uint16_t _vid = UINT16_MAX;
-        uint16_t _vid_end = UINT16_MAX;
-
-        assert(rvalue);
-        assert(vid);
-        assert(vid_end);
-
-        _rvalue = strdupa(rvalue);
-        p = strchr(_rvalue, '-');
-        if (p) {
-                *p = '\0';
-                p++;
-                r = parse_vlanid(_rvalue, &_vid);
-                if (r < 0)
-                        return r;
-
-                if (_vid == 0)
-                        return -ERANGE;
-
-                r = parse_vlanid(p, &_vid_end);
-                if (r < 0)
-                        return r;
-
-                if (_vid_end == 0)
-                        return -ERANGE;
-        } else {
-                r = parse_vlanid(_rvalue, &_vid);
-                if (r < 0)
-                        return r;
-
-                if (_vid == 0)
-                        return -ERANGE;
-        }
-
-        *vid = _vid;
-        *vid_end = _vid_end;
-        return r;
-}
-
 int config_parse_brvlan_pvid(const char *unit, const char *filename,
                              unsigned line, const char *section,
                              unsigned section_line, const char *lvalue,
                              int ltype, const char *rvalue, void *data,
                              void *userdata) {
         Network *network = userdata;
-        int r;
         uint16_t pvid;
+        int r;
+
         r = parse_vlanid(rvalue, &pvid);
         if (r < 0)
                 return r;
@@ -271,8 +228,8 @@ int config_parse_brvlan_vlan(const char *unit, const char *filename,
                              int ltype, const char *rvalue, void *data,
                              void *userdata) {
         Network *network = userdata;
-        int r;
         uint16_t vid, vid_end;
+        int r;
 
         assert(filename);
         assert(section);
@@ -286,16 +243,9 @@ int config_parse_brvlan_vlan(const char *unit, const char *filename,
                 return 0;
         }
 
-        if (UINT16_MAX == vid_end)
-                set_bit(vid++, network->br_vid_bitmap);
-        else {
-                if (vid >= vid_end) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
-                        return 0;
-                }
-                for (; vid <= vid_end; vid++)
-                        set_bit(vid, network->br_vid_bitmap);
-        }
+        for (; vid <= vid_end; vid++)
+                set_bit(vid, network->br_vid_bitmap);
+
         network->use_br_vlan = true;
         return 0;
 }
@@ -321,19 +271,11 @@ int config_parse_brvlan_untagged(const char *unit, const char *filename,
                 return 0;
         }
 
-        if (UINT16_MAX == vid_end) {
+        for (; vid <= vid_end; vid++) {
                 set_bit(vid, network->br_vid_bitmap);
                 set_bit(vid, network->br_untagged_bitmap);
-        } else {
-                if (vid >= vid_end) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
-                        return 0;
-                }
-                for (; vid <= vid_end; vid++) {
-                        set_bit(vid, network->br_vid_bitmap);
-                        set_bit(vid, network->br_untagged_bitmap);
-                }
         }
+
         network->use_br_vlan = true;
         return 0;
 }
index f6af140d3eee79d83f458c6317e0c510eedec976..7533034021690c9ec7694e0b08109e17a385ff53 100644 (file)
@@ -9,6 +9,9 @@
 
 #include "conf-parser.h"
 
+#define BRIDGE_VLAN_BITMAP_MAX 4096
+#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
+
 typedef struct Link Link;
 
 int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c
new file mode 100644 (file)
index 0000000..743f2d8
--- /dev/null
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "networkd-dhcp-common.h"
+#include "networkd-network.h"
+#include "parse-util.h"
+#include "string-table.h"
+
+int config_parse_dhcp(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        AddressFamilyBoolean *dhcp = data, s;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        /* Note that this is mostly like
+         * config_parse_address_family_boolean(), except that it
+         * understands some old names for the enum values */
+
+        s = address_family_boolean_from_string(rvalue);
+        if (s < 0) {
+
+                /* Previously, we had a slightly different enum here,
+                 * support its values for compatibility. */
+
+                if (streq(rvalue, "none"))
+                        s = ADDRESS_FAMILY_NO;
+                else if (streq(rvalue, "v4"))
+                        s = ADDRESS_FAMILY_IPV4;
+                else if (streq(rvalue, "v6"))
+                        s = ADDRESS_FAMILY_IPV6;
+                else if (streq(rvalue, "both"))
+                        s = ADDRESS_FAMILY_YES;
+                else {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Failed to parse DHCP option, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "DHCP=%s is deprecated, please use DHCP=%s instead.",
+                           rvalue, address_family_boolean_to_string(s));
+        }
+
+        *dhcp = s;
+        return 0;
+}
+
+int config_parse_section_route_table(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        uint32_t rt;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou32(rvalue, &rt);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+                return 0;
+        }
+
+        if (streq_ptr(section, "DHCP")) {
+                network->dhcp_route_table = rt;
+                network->dhcp_route_table_set = true;
+        } else { /* section is IPv6AcceptRA */
+                network->ipv6_accept_ra_route_table = rt;
+                network->ipv6_accept_ra_route_table_set = true;
+        }
+
+        return 0;
+}
+
+int config_parse_iaid(const char *unit,
+                      const char *filename,
+                      unsigned line,
+                      const char *section,
+                      unsigned section_line,
+                      const char *lvalue,
+                      int ltype,
+                      const char *rvalue,
+                      void *data,
+                      void *userdata) {
+        Network *network = data;
+        uint32_t iaid;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(network);
+
+        r = safe_atou32(rvalue, &iaid);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Unable to read IAID, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        network->iaid = iaid;
+        network->iaid_set = true;
+
+        return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
+                         "Failed to parse DHCP use domains setting");
+
+static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
+        [DHCP_USE_DOMAINS_NO] = "no",
+        [DHCP_USE_DOMAINS_ROUTE] = "route",
+        [DHCP_USE_DOMAINS_YES] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h
new file mode 100644 (file)
index 0000000..0e6e051
--- /dev/null
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+#include "dhcp-identifier.h"
+#include "time-util.h"
+
+#define DHCP_ROUTE_METRIC 1024
+
+typedef enum DHCPUseDomains {
+        DHCP_USE_DOMAINS_NO,
+        DHCP_USE_DOMAINS_YES,
+        DHCP_USE_DOMAINS_ROUTE,
+        _DHCP_USE_DOMAINS_MAX,
+        _DHCP_USE_DOMAINS_INVALID = -1,
+} DHCPUseDomains;
+
+typedef struct DUID {
+        /* Value of Type in [DHCP] section */
+        DUIDType type;
+
+        uint8_t raw_data_len;
+        uint8_t raw_data[MAX_DUID_LEN];
+        usec_t llt_time;
+} DUID;
+
+const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
+DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
+CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
new file mode 100644 (file)
index 0000000..f4c2178
--- /dev/null
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-dhcp-server.h"
+
+#include "networkd-dhcp-server.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "networkd-network.h"
+#include "strv.h"
+
+static Address* link_find_dhcp_server_address(Link *link) {
+        Address *address;
+
+        assert(link);
+        assert(link->network);
+
+        /* The first statically configured address if there is any */
+        LIST_FOREACH(addresses, address, link->network->static_addresses) {
+
+                if (address->family != AF_INET)
+                        continue;
+
+                if (in_addr_is_null(address->family, &address->in_addr))
+                        continue;
+
+                return address;
+        }
+
+        /* If that didn't work, find a suitable address we got from the pool */
+        LIST_FOREACH(addresses, address, link->pool_addresses) {
+                if (address->family != AF_INET)
+                        continue;
+
+                return address;
+        }
+
+        return NULL;
+}
+
+static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+        _cleanup_free_ struct in_addr *addresses = NULL;
+        size_t n_addresses = 0, n_allocated = 0;
+        unsigned i;
+
+        log_debug("Copying DNS server information from %s", link->ifname);
+
+        if (!link->network)
+                return 0;
+
+        for (i = 0; i < link->network->n_dns; i++) {
+                struct in_addr ia;
+
+                /* Only look for IPv4 addresses */
+                if (link->network->dns[i].family != AF_INET)
+                        continue;
+
+                ia = link->network->dns[i].address.in;
+
+                /* Never propagate obviously borked data */
+                if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
+                        continue;
+
+                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+                        return log_oom();
+
+                addresses[n_addresses++] = ia;
+        }
+
+        if (link->network->dhcp_use_dns && link->dhcp_lease) {
+                const struct in_addr *da = NULL;
+                int j, n;
+
+                n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
+                if (n > 0) {
+
+                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+                                return log_oom();
+
+                        for (j = 0; j < n; j++)
+                                if (in4_addr_is_non_local(&da[j]))
+                                        addresses[n_addresses++] = da[j];
+                }
+        }
+
+        if (n_addresses <= 0)
+                return 0;
+
+        return sd_dhcp_server_set_dns(s, addresses, n_addresses);
+}
+
+static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+        _cleanup_free_ struct in_addr *addresses = NULL;
+        size_t n_addresses = 0, n_allocated = 0;
+        char **a;
+
+        if (!link->network)
+                return 0;
+
+        log_debug("Copying NTP server information from %s", link->ifname);
+
+        STRV_FOREACH(a, link->network->ntp) {
+                union in_addr_union ia;
+
+                /* Only look for IPv4 addresses */
+                if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
+                        continue;
+
+                /* Never propagate obviously borked data */
+                if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+                        continue;
+
+                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+                        return log_oom();
+
+                addresses[n_addresses++] = ia.in;
+        }
+
+        if (link->network->dhcp_use_ntp && link->dhcp_lease) {
+                const struct in_addr *da = NULL;
+                int j, n;
+
+                n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
+                if (n > 0) {
+
+                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+                                return log_oom();
+
+                        for (j = 0; j < n; j++)
+                                if (in4_addr_is_non_local(&da[j]))
+                                        addresses[n_addresses++] = da[j];
+                }
+        }
+
+        if (n_addresses <= 0)
+                return 0;
+
+        return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
+}
+
+int dhcp4_server_configure(Link *link) {
+        Address *address;
+        Link *uplink = NULL;
+        bool acquired_uplink = false;
+        int r;
+
+        address = link_find_dhcp_server_address(link);
+        if (!address)
+                return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBUSY),
+                                              "Failed to find suitable address for DHCPv4 server instance.");
+
+        /* use the server address' subnet as the pool */
+        r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
+                                          link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
+        if (r < 0)
+                return r;
+
+        /* TODO:
+        r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in);
+        if (r < 0)
+                return r;
+        */
+
+        if (link->network->dhcp_server_max_lease_time_usec > 0) {
+                r = sd_dhcp_server_set_max_lease_time(link->dhcp_server,
+                                                      DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
+                if (r < 0)
+                        return r;
+        }
+
+        if (link->network->dhcp_server_default_lease_time_usec > 0) {
+                r = sd_dhcp_server_set_default_lease_time(link->dhcp_server,
+                                                          DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
+                if (r < 0)
+                        return r;
+        }
+
+        if (link->network->dhcp_server_emit_dns) {
+                if (link->network->n_dhcp_server_dns > 0)
+                        r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
+                else {
+                        uplink = manager_find_uplink(link->manager, link);
+                        acquired_uplink = true;
+
+                        if (!uplink) {
+                                log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
+                                r = 0;
+                        } else
+                                r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
+                }
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
+        }
+
+        if (link->network->dhcp_server_emit_ntp) {
+                if (link->network->n_dhcp_server_ntp > 0)
+                        r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
+                else {
+                        if (!acquired_uplink)
+                                uplink = manager_find_uplink(link->manager, link);
+
+                        if (!uplink) {
+                                log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
+                                r = 0;
+                        } else
+                                r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
+
+                }
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
+        }
+
+        r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
+
+        if (link->network->dhcp_server_emit_timezone) {
+                _cleanup_free_ char *buffer = NULL;
+                const char *tz;
+
+                if (link->network->dhcp_server_timezone)
+                        tz = link->network->dhcp_server_timezone;
+                else {
+                        r = get_timezone(&buffer);
+                        if (r < 0)
+                                return log_warning_errno(r, "Failed to determine timezone: %m");
+
+                        tz = buffer;
+                }
+
+                r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
+                if (r < 0)
+                        return r;
+        }
+        if (!sd_dhcp_server_is_running(link->dhcp_server)) {
+                r = sd_dhcp_server_start(link->dhcp_server);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
+        }
+
+        return 0;
+}
+
+int config_parse_dhcp_server_dns(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *n = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+                union in_addr_union a;
+                struct in_addr *m;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract word, ignoring: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
+
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
+                        continue;
+                }
+
+                m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
+                if (!m)
+                        return log_oom();
+
+                m[n->n_dhcp_server_dns++] = a.in;
+                n->dhcp_server_dns = m;
+        }
+
+        return 0;
+}
+
+int config_parse_dhcp_server_ntp(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *n = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+                union in_addr_union a;
+                struct in_addr *m;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract word, ignoring: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse NTP server address '%s', ignoring: %m", w);
+                        continue;
+                }
+
+                m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
+                if (!m)
+                        return log_oom();
+
+                m[n->n_dhcp_server_ntp++] = a.in;
+                n->dhcp_server_ntp = m;
+        }
+}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
new file mode 100644 (file)
index 0000000..e97e56b
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+int dhcp4_server_configure(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
index 978378d7b8217336fc344733e16533618f04b065..c0d776f464b75b5b541e944e9fd06f90229dfa38 100644 (file)
@@ -7,9 +7,11 @@
 #include "hostname-util.h"
 #include "parse-util.h"
 #include "network-internal.h"
+#include "networkd-dhcp4.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "networkd-network.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "sysctl-util.h"
 
@@ -145,6 +147,8 @@ static int link_set_dhcp_routes(Link *link) {
                 route->priority = link->network->dhcp_route_metric;
                 route->table = table;
                 route->scope = route_scope_from_address(route, &address);
+                if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
+                        route->prefsrc.in = address;
 
                 r = route_configure(route, link, dhcp4_route_handler);
                 if (r < 0)
@@ -275,6 +279,8 @@ static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, sd_dhcp_lease *n
                 route->priority = link->network->dhcp_route_metric;
                 route->table = table;
                 route->scope = route_scope_from_address(route, address);
+                if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
+                        route->prefsrc.in = *address;
 
                 if (route_present_in_routes(route, new_routes, m))
                         continue;
@@ -1078,3 +1084,175 @@ int dhcp4_configure(Link *link) {
 
         return dhcp4_set_client_identifier(link);
 }
+
+int config_parse_dhcp_max_attempts(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        uint64_t a;
+        int r;
+
+        assert(network);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                network->dhcp_max_attempts = 0;
+                return 0;
+        }
+
+        if (streq(rvalue, "infinity")) {
+                network->dhcp_max_attempts = (uint64_t) -1;
+                return 0;
+        }
+
+        r = safe_atou64(rvalue, &a);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (a == 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        network->dhcp_max_attempts = a;
+
+        return 0;
+}
+
+int config_parse_dhcp_black_listed_ip_address(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                union in_addr_union ip;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET, n, &ip);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
+                if (r < 0)
+                        return log_oom();
+
+                r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
+        }
+
+        return 0;
+}
+
+int config_parse_dhcp_user_class(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        char ***l = data;
+        int r;
+
+        assert(l);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *l = strv_free(*l);
+                return 0;
+        }
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+
+                r = extract_first_word(&rvalue, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to split user classes option, ignoring: %s", rvalue);
+                        break;
+                }
+                if (r == 0)
+                        break;
+
+                if (strlen(w) > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "%s length is not in the range 1-255, ignoring.", w);
+                        continue;
+                }
+
+                r = strv_push(l, w);
+                if (r < 0)
+                        return log_oom();
+
+                w = NULL;
+        }
+
+        return 0;
+}
+
+static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
+        [DHCP_CLIENT_ID_MAC] = "mac",
+        [DHCP_CLIENT_ID_DUID] = "duid",
+        [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
+                         "Failed to parse client identifier type");
diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h
new file mode 100644 (file)
index 0000000..117b711
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+typedef enum DHCPClientIdentifier {
+        DHCP_CLIENT_ID_MAC,
+        DHCP_CLIENT_ID_DUID,
+        /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
+         * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
+         * requires the client id to be set to a custom string, reported at
+         * https://github.com/systemd/systemd/issues/7828 */
+        DHCP_CLIENT_ID_DUID_ONLY,
+        _DHCP_CLIENT_ID_MAX,
+        _DHCP_CLIENT_ID_INVALID = -1,
+} DHCPClientIdentifier;
+
+void dhcp4_release_old_lease(Link *link);
+int dhcp4_configure(Link *link);
+int dhcp4_set_client_identifier(Link *link);
+int dhcp4_set_promote_secondaries(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
index afa3e2cfd68a883d06aa0247825585c337ee4f92..286b9071ae7c91e6678afd58ce23faf7d482df94 100644 (file)
@@ -13,6 +13,7 @@
 #include "hostname-util.h"
 #include "missing_network.h"
 #include "network-internal.h"
+#include "networkd-dhcp6.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
 #include "siphash24.h"
@@ -20,6 +21,9 @@
 #include "radv-internal.h"
 
 static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
+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_get_prefix_delegation(Link *link) {
         if (!link->network)
@@ -90,7 +94,7 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
         if (r < 0 && r != -EEXIST)
                 return r;
 
-        r = manager_dhcp6_prefix_add(link->manager, prefix, link);
+        r = dhcp6_prefix_add(link->manager, prefix, link);
         if (r < 0)
                 return r;
 
@@ -104,7 +108,7 @@ static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Lin
 
         r = sd_netlink_message_get_errno(m);
         if (r < 0)
-                log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m");
+                log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnet: %m");
 
         return 1;
 }
@@ -202,7 +206,7 @@ static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i,
                 if (!dhcp6_get_prefix_delegation(link))
                         continue;
 
-                assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6);
+                assigned_link = dhcp6_prefix_get(manager, &prefix.in6);
                 if (assigned_link && assigned_link != link)
                         continue;
 
@@ -488,7 +492,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
                         log_link_warning(link, "DHCPv6 lease lost");
 
                 (void) dhcp6_lease_pd_prefix_lost(client, link);
-                (void) manager_dhcp6_prefix_remove_all(link->manager, link);
+                (void) dhcp6_prefix_remove_all(link->manager, link);
 
                 link->dhcp6_configured = false;
                 break;
@@ -685,3 +689,123 @@ int dhcp6_configure(Link *link) {
 
         return 0;
 }
+
+static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
+        assert_return(m, NULL);
+        assert_return(addr, NULL);
+
+        return hashmap_get(m->dhcp6_prefixes, addr);
+}
+
+static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0 && r != -EEXIST)
+                log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
+
+        return 0;
+}
+
+static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
+        _cleanup_free_ struct in6_addr *a = NULL;
+        _cleanup_free_ char *buf = NULL;
+        Link *assigned_link;
+        Route *route;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(addr, -EINVAL);
+
+        r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
+                      0, 0, 0, &route);
+        if (r < 0)
+                return r;
+
+        r = route_configure(route, link, dhcp6_route_add_handler);
+        if (r < 0)
+                return r;
+
+        (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
+        log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
+
+        assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
+        if (assigned_link) {
+                assert(assigned_link == link);
+                return 0;
+        }
+
+        a = newdup(struct in6_addr, addr, 1);
+        if (!a)
+                return -ENOMEM;
+
+        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
+        if (r < 0)
+                return r;
+
+        r = hashmap_put(m->dhcp6_prefixes, a, link);
+        if (r < 0)
+                return r;
+
+        TAKE_PTR(a);
+        link_ref(link);
+        return 0;
+}
+
+static int dhcp6_prefix_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0)
+                log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
+
+        return 1;
+}
+
+int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
+        _cleanup_free_ struct in6_addr *a = NULL;
+        _cleanup_(link_unrefp) Link *l = NULL;
+        _cleanup_free_ char *buf = NULL;
+        Route *route;
+        int r;
+
+        assert_return(m, -EINVAL);
+        assert_return(addr, -EINVAL);
+
+        l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
+        if (!l)
+                return -EINVAL;
+
+        (void) sd_radv_remove_prefix(l->radv, addr, 64);
+        r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
+        if (r < 0)
+                return r;
+
+        r = route_remove(route, l, dhcp6_prefix_remove_handler);
+        if (r < 0)
+                return r;
+
+        (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
+        log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
+
+        return 0;
+}
+
+static int dhcp6_prefix_remove_all(Manager *m, Link *link) {
+        struct in6_addr *addr;
+        Iterator i;
+        Link *l;
+
+        assert_return(m, -EINVAL);
+        assert_return(link, -EINVAL);
+
+        HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
+                if (l == link)
+                        (void) dhcp6_prefix_remove(m, addr);
+
+        return 0;
+}
diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h
new file mode 100644 (file)
index 0000000..26d810f
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-dhcp6-client.h"
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+typedef struct Manager Manager;
+
+int dhcp6_request_prefix_delegation(Link *link);
+int dhcp6_configure(Link *link);
+int dhcp6_request_address(Link *link, int ir);
+int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
+int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
index 738d22cb5bc408d02ed10cee7c1b3557254c5702..d76f02d56397c944efc4cecb9689e2ac770cfee7 100644 (file)
@@ -5,8 +5,10 @@
 
 #include "network-internal.h"
 #include "networkd-address.h"
-#include "networkd-manager.h"
+#include "networkd-ipv4ll.h"
 #include "networkd-link.h"
+#include "networkd-manager.h"
+#include "parse-util.h"
 
 static int ipv4ll_address_lost(Link *link) {
         _cleanup_(address_freep) Address *address = NULL;
@@ -234,3 +236,45 @@ int ipv4ll_configure(Link *link) {
 
         return 0;
 }
+
+int config_parse_ipv4ll(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        AddressFamilyBoolean *link_local = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        /* Note that this is mostly like
+         * config_parse_address_family_boolean(), except that it
+         * applies only to IPv4 */
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to parse %s=%s, ignoring assignment. "
+                           "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
+                           lvalue, rvalue, lvalue);
+                return 0;
+        }
+
+        SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
+                   lvalue, rvalue, address_family_boolean_to_string(*link_local));
+
+        return 0;
+}
diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h
new file mode 100644 (file)
index 0000000..49b6fb5
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+#define IPV4LL_ROUTE_METRIC 2048
+
+typedef struct Link Link;
+
+int ipv4ll_configure(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
index 9f228a9d30417b0fcf3e8e4cfafe7256ce72a78e..d206589bc4f5630c8b091b450450747bdb5a59f7 100644 (file)
 #include "netlink-util.h"
 #include "network-internal.h"
 #include "networkd-can.h"
+#include "networkd-dhcp-server.h"
+#include "networkd-dhcp4.h"
+#include "networkd-dhcp6.h"
+#include "networkd-ipv4ll.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-link-bus.h"
 #include "networkd-link.h"
@@ -68,11 +72,18 @@ int link_sysctl_ipv6_enabled(Link *link) {
         _cleanup_free_ char *value = NULL;
         int r;
 
-        r = sysctl_read_ip_property(AF_INET6, link->ifname, "disable_ipv6", &value);
+        assert(link);
+        assert(link->ifname);
+
+        if (link->sysctl_ipv6_enabled >= 0)
+                return link->sysctl_ipv6_enabled;
+
+        const char *ifname = link->ifname; /* work around bogus gcc warning */
+        r = sysctl_read_ip_property(AF_INET6, ifname, "disable_ipv6", &value);
         if (r < 0)
                 return log_link_warning_errno(link, r,
                                               "Failed to read net.ipv6.conf.%s.disable_ipv6 sysctl property: %m",
-                                              link->ifname);
+                                              ifname);
 
         link->sysctl_ipv6_enabled = value[0] == '0';
         return link->sysctl_ipv6_enabled;
@@ -148,7 +159,9 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon"))
+        if (STRPTR_IN_SET(link->kind,
+                          "vrf", "wireguard", "ipip", "gre", "ip6gre","ip6tnl", "sit", "vti",
+                          "vti6", "can", "vcan", "vxcan", "nlmon", "xfrm"))
                 return false;
 
         /* L3 or L3S mode do not support ARP. */
@@ -158,9 +171,6 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         if (link->network->bond)
                 return false;
 
-        if (link->network->bond)
-                return false;
-
         return link->network->link_local & mask;
 }
 
@@ -797,35 +807,6 @@ void link_enter_failed(Link *link) {
         link_dirty(link);
 }
 
-static Address* link_find_dhcp_server_address(Link *link) {
-        Address *address;
-
-        assert(link);
-        assert(link->network);
-
-        /* The first statically configured address if there is any */
-        LIST_FOREACH(addresses, address, link->network->static_addresses) {
-
-                if (address->family != AF_INET)
-                        continue;
-
-                if (in_addr_is_null(address->family, &address->in_addr))
-                        continue;
-
-                return address;
-        }
-
-        /* If that didn't work, find a suitable address we got from the pool */
-        LIST_FOREACH(addresses, address, link->pool_addresses) {
-                if (address->family != AF_INET)
-                        continue;
-
-                return address;
-        }
-
-        return NULL;
-}
-
 static int link_join_netdevs_after_configured(Link *link) {
         NetDev *netdev;
         Iterator i;
@@ -1104,106 +1085,6 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         return 1;
 }
 
-static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
-        _cleanup_free_ struct in_addr *addresses = NULL;
-        size_t n_addresses = 0, n_allocated = 0;
-        unsigned i;
-
-        log_debug("Copying DNS server information from %s", link->ifname);
-
-        if (!link->network)
-                return 0;
-
-        for (i = 0; i < link->network->n_dns; i++) {
-                struct in_addr ia;
-
-                /* Only look for IPv4 addresses */
-                if (link->network->dns[i].family != AF_INET)
-                        continue;
-
-                ia = link->network->dns[i].address.in;
-
-                /* Never propagate obviously borked data */
-                if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
-                        continue;
-
-                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
-                        return log_oom();
-
-                addresses[n_addresses++] = ia;
-        }
-
-        if (link->network->dhcp_use_dns && link->dhcp_lease) {
-                const struct in_addr *da = NULL;
-                int j, n;
-
-                n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
-                if (n > 0) {
-
-                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
-                                return log_oom();
-
-                        for (j = 0; j < n; j++)
-                                if (in4_addr_is_non_local(&da[j]))
-                                        addresses[n_addresses++] = da[j];
-                }
-        }
-
-        if (n_addresses <= 0)
-                return 0;
-
-        return sd_dhcp_server_set_dns(s, addresses, n_addresses);
-}
-
-static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
-        _cleanup_free_ struct in_addr *addresses = NULL;
-        size_t n_addresses = 0, n_allocated = 0;
-        char **a;
-
-        if (!link->network)
-                return 0;
-
-        log_debug("Copying NTP server information from %s", link->ifname);
-
-        STRV_FOREACH(a, link->network->ntp) {
-                union in_addr_union ia;
-
-                /* Only look for IPv4 addresses */
-                if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
-                        continue;
-
-                /* Never propagate obviously borked data */
-                if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
-                        continue;
-
-                if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
-                        return log_oom();
-
-                addresses[n_addresses++] = ia.in;
-        }
-
-        if (link->network->dhcp_use_ntp && link->dhcp_lease) {
-                const struct in_addr *da = NULL;
-                int j, n;
-
-                n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
-                if (n > 0) {
-
-                        if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
-                                return log_oom();
-
-                        for (j = 0; j < n; j++)
-                                if (in4_addr_is_non_local(&da[j]))
-                                        addresses[n_addresses++] = da[j];
-                }
-        }
-
-        if (n_addresses <= 0)
-                return 0;
-
-        return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
-}
-
 static int link_set_bridge_fdb(Link *link) {
         FdbEntry *fdb_entry;
         int r;
@@ -1272,118 +1153,11 @@ static int link_request_set_addresses(Link *link) {
         /* now that we can figure out a default address for the dhcp server,
            start it */
         if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) {
-                Address *address;
-                Link *uplink = NULL;
-                bool acquired_uplink = false;
-
-                address = link_find_dhcp_server_address(link);
-                if (!address) {
-                        log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
+                r = dhcp4_server_configure(link);
+                if (r < 0) {
                         link_enter_failed(link);
-                        return 0;
-                }
-
-                /* use the server address' subnet as the pool */
-                r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
-                                                  link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
-                if (r < 0)
                         return r;
-
-                /* TODO:
-                r = sd_dhcp_server_set_router(link->dhcp_server,
-                                              &main_address->in_addr.in);
-                if (r < 0)
-                        return r;
-                */
-
-                if (link->network->dhcp_server_max_lease_time_usec > 0) {
-                        r = sd_dhcp_server_set_max_lease_time(
-                                        link->dhcp_server,
-                                        DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
-                        if (r < 0)
-                                return r;
-                }
-
-                if (link->network->dhcp_server_default_lease_time_usec > 0) {
-                        r = sd_dhcp_server_set_default_lease_time(
-                                        link->dhcp_server,
-                                        DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
-                        if (r < 0)
-                                return r;
-                }
-
-                if (link->network->dhcp_server_emit_dns) {
-
-                        if (link->network->n_dhcp_server_dns > 0)
-                                r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
-                        else {
-                                uplink = manager_find_uplink(link->manager, link);
-                                acquired_uplink = true;
-
-                                if (!uplink) {
-                                        log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
-                                        r = 0;
-                                } else
-                                        r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
-                        }
-                        if (r < 0)
-                                log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
-                }
-
-                if (link->network->dhcp_server_emit_ntp) {
-
-                        if (link->network->n_dhcp_server_ntp > 0)
-                                r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
-                        else {
-                                if (!acquired_uplink)
-                                        uplink = manager_find_uplink(link->manager, link);
-
-                                if (!uplink) {
-                                        log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
-                                        r = 0;
-                                } else
-                                        r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
-
-                        }
-                        if (r < 0)
-                                log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
-                }
-
-                r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
-
-                if (link->network->dhcp_server_emit_timezone) {
-                        _cleanup_free_ char *buffer = NULL;
-                        const char *tz = NULL;
-
-                        if (link->network->dhcp_server_timezone)
-                                tz = link->network->dhcp_server_timezone;
-                        else {
-                                r = get_timezone(&buffer);
-                                if (r < 0)
-                                        log_warning_errno(r, "Failed to determine timezone: %m");
-                                else
-                                        tz = buffer;
-                        }
-
-                        if (tz) {
-                                r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
-                                if (r < 0)
-                                        return r;
-                        }
                 }
-                if (!sd_dhcp_server_is_running(link->dhcp_server)) {
-                        r = sd_dhcp_server_start(link->dhcp_server);
-                        if (r < 0) {
-                                log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
-
-                                link_enter_failed(link);
-
-                                return 0;
-                        }
-                }
-
                 log_link_debug(link, "Offering DHCPv4 leases");
         }
 
index ac1532c066fc2171014fb6e9791dd10b1065c18a..43efa42312412ede531cc4c299f64746fc0d915c 100644 (file)
@@ -168,18 +168,8 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
 
 int link_set_mtu(Link *link, uint32_t mtu);
 
-int ipv4ll_configure(Link *link);
 bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask);
 
-void dhcp4_release_old_lease(Link *link);
-int dhcp4_configure(Link *link);
-int dhcp4_set_client_identifier(Link *link);
-int dhcp4_set_promote_secondaries(Link *link);
-int dhcp6_request_prefix_delegation(Link *link);
-int dhcp6_configure(Link *link);
-int dhcp6_request_address(Link *link, int ir);
-int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
-
 int link_stop_clients(Link *link, bool may_keep_dhcp);
 
 const char* link_state_to_string(LinkState s) _const_;
index ea82268cd5ad9763ac1f60fbf5a4b30e2716b727..33b7ec1d6c33f7266f274e10d3d48058c4206fb9 100644 (file)
 #include "local-addresses.h"
 #include "netlink-util.h"
 #include "network-internal.h"
+#include "networkd-dhcp6.h"
 #include "networkd-link-bus.h"
 #include "networkd-manager.h"
+#include "networkd-network-bus.h"
 #include "networkd-speed-meter.h"
 #include "ordered-set.h"
 #include "path-util.h"
@@ -1313,126 +1315,6 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) {
         return 1;
 }
 
-Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
-        assert_return(m, NULL);
-        assert_return(addr, NULL);
-
-        return hashmap_get(m->dhcp6_prefixes, addr);
-}
-
-static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0 && r != -EEXIST)
-                log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
-
-        return 0;
-}
-
-int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
-        _cleanup_free_ struct in6_addr *a = NULL;
-        _cleanup_free_ char *buf = NULL;
-        Link *assigned_link;
-        Route *route;
-        int r;
-
-        assert_return(m, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
-                      0, 0, 0, &route);
-        if (r < 0)
-                return r;
-
-        r = route_configure(route, link, dhcp6_route_add_handler);
-        if (r < 0)
-                return r;
-
-        (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
-        log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
-
-        assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
-        if (assigned_link) {
-                assert(assigned_link == link);
-                return 0;
-        }
-
-        a = newdup(struct in6_addr, addr, 1);
-        if (!a)
-                return -ENOMEM;
-
-        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
-        if (r < 0)
-                return r;
-
-        r = hashmap_put(m->dhcp6_prefixes, a, link);
-        if (r < 0)
-                return r;
-
-        TAKE_PTR(a);
-        link_ref(link);
-        return 0;
-}
-
-static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0)
-                log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
-
-        return 1;
-}
-
-static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
-        _cleanup_free_ struct in6_addr *a = NULL;
-        _cleanup_(link_unrefp) Link *l = NULL;
-        _cleanup_free_ char *buf = NULL;
-        Route *route;
-        int r;
-
-        assert_return(m, -EINVAL);
-        assert_return(addr, -EINVAL);
-
-        l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
-        if (!l)
-                return -EINVAL;
-
-        (void) sd_radv_remove_prefix(l->radv, addr, 64);
-        r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
-        if (r < 0)
-                return r;
-
-        r = route_remove(route, l, dhcp6_route_remove_handler);
-        if (r < 0)
-                return r;
-
-        (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
-        log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
-
-        return 0;
-}
-
-int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) {
-        struct in6_addr *addr;
-        Iterator i;
-        Link *l;
-
-        assert_return(m, -EINVAL);
-        assert_return(link, -EINVAL);
-
-        HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
-                if (l == link)
-                        (void) manager_dhcp6_prefix_remove(m, addr);
-
-        return 0;
-}
-
 int manager_new(Manager **ret) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
@@ -1505,7 +1387,7 @@ void manager_free(Manager *m) {
         free(m->state_file);
 
         while ((a = hashmap_first_key(m->dhcp6_prefixes)))
-                (void) manager_dhcp6_prefix_remove(m, a);
+                (void) dhcp6_prefix_remove(m, a);
         hashmap_free(m->dhcp6_prefixes);
 
         while ((link = hashmap_steal_first(m->links))) {
index e0ec45aa2f1d6e96a82c415c0077fb8722973748..9b3b05bccc3a1b00bb3a59e5de00841b697751f7 100644 (file)
@@ -96,8 +96,4 @@ int manager_set_hostname(Manager *m, const char *hostname);
 int manager_set_timezone(Manager *m, const char *timezone);
 int manager_request_product_uuid(Manager *m, Link *link);
 
-Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
-int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
-int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
-
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
index 0d2fde2f742a43bf14fdf38e6ca7cb68844d9e5a..78f89e026e4f035e35398145472abbcfb35c0a4f 100644 (file)
@@ -9,6 +9,7 @@
 #include "sd-ndisc.h"
 
 #include "missing_network.h"
+#include "networkd-dhcp6.h"
 #include "networkd-ndisc.h"
 #include "networkd-route.h"
 #include "strv.h"
@@ -763,6 +764,9 @@ int config_parse_ndisc_black_listed_prefix(
                         continue;
                 }
 
+                if (set_contains(network->ndisc_black_listed_prefix, &ip.in6))
+                        continue;
+
                 r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
                 if (r < 0)
                         return log_oom();
@@ -773,12 +777,8 @@ int config_parse_ndisc_black_listed_prefix(
 
                 r = set_put(network->ndisc_black_listed_prefix, a);
                 if (r < 0) {
-                        if (r == -EEXIST)
-                                log_syntax(unit, LOG_WARNING, filename, line, r,
-                                           "NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
-                        else
-                                log_syntax(unit, LOG_ERR, filename, line, r,
-                                           "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
                         continue;
                 }
 
index e3ba148ce1bf744d171fb5f68145436494bb89bc..a895f7268882f9de14d3e19d9e8c70e82aa932d5 100644 (file)
@@ -3,6 +3,7 @@
 #include "alloc-util.h"
 #include "ether-addr-util.h"
 #include "networkd-manager.h"
+#include "networkd-network-bus.h"
 #include "string-util.h"
 #include "strv.h"
 
diff --git a/src/network/networkd-network-bus.h b/src/network/networkd-network-bus.h
new file mode 100644 (file)
index 0000000..650e145
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+typedef struct Link Link;
+
+extern const sd_bus_vtable network_vtable[];
+
+int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
index 2986ff1123d92c95cd3c9b356f8864410abba513..5a2f3f4ea9f640520e5b2de00143069908c656dc 100644 (file)
@@ -6,6 +6,10 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "conf-parser.h"
 #include "network-internal.h"
 #include "networkd-conf.h"
+#include "networkd-dhcp-common.h"
+#include "networkd-dhcp-server.h"
+#include "networkd-dhcp4.h"
+#include "networkd-ipv4ll.h"
 #include "networkd-ndisc.h"
 #include "networkd-network.h"
 #include "vlan-util.h"
@@ -22,10 +26,11 @@ struct ConfigPerfItem;
 %includes
 %%
 Match.MACAddress,                       config_parse_hwaddrs,                            0,                             offsetof(Network, match_mac)
-Match.Path,                             config_parse_strv,                               0,                             offsetof(Network, match_path)
-Match.Driver,                           config_parse_strv,                               0,                             offsetof(Network, match_driver)
-Match.Type,                             config_parse_strv,                               0,                             offsetof(Network, match_type)
-Match.Name,                             config_parse_ifnames,                            0,                             offsetof(Network, match_name)
+Match.Path,                             config_parse_match_strv,                         0,                             offsetof(Network, match_path)
+Match.Driver,                           config_parse_match_strv,                         0,                             offsetof(Network, match_driver)
+Match.Type,                             config_parse_match_strv,                         0,                             offsetof(Network, match_type)
+Match.Name,                             config_parse_match_ifnames,                      0,                             offsetof(Network, match_name)
+Match.Property,                         config_parse_match_property,                     0,                             offsetof(Network, match_property)
 Match.Host,                             config_parse_net_condition,                      CONDITION_HOST,                offsetof(Network, conditions)
 Match.Virtualization,                   config_parse_net_condition,                      CONDITION_VIRTUALIZATION,      offsetof(Network, conditions)
 Match.KernelCommandLine,                config_parse_net_condition,                      CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
@@ -50,6 +55,7 @@ Network.VXLAN,                          config_parse_stacked_netdev,
 Network.L2TP,                           config_parse_stacked_netdev,                     NETDEV_KIND_L2TP,              offsetof(Network, stacked_netdev_names)
 Network.MACsec,                         config_parse_stacked_netdev,                     NETDEV_KIND_MACSEC,            offsetof(Network, stacked_netdev_names)
 Network.Tunnel,                         config_parse_stacked_netdev,                     _NETDEV_KIND_TUNNEL,           offsetof(Network, stacked_netdev_names)
+Network.Xfrm,                           config_parse_stacked_netdev,                     NETDEV_KIND_XFRM,              offsetof(Network, stacked_netdev_names)
 Network.VRF,                            config_parse_ifname,                             0,                             offsetof(Network, vrf_name)
 Network.DHCP,                           config_parse_dhcp,                               0,                             offsetof(Network, dhcp)
 Network.DHCPServer,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server)
index 0741dfe646de626b43a9703b65a590c2440f5cf0..3f1753049ceadabb18014edc52bdd89fa67cb453 100644 (file)
@@ -157,7 +157,8 @@ int network_verify(Network *network) {
 
         if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
             strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
-            strv_isempty(network->match_name) && !network->conditions)
+            strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
+            !network->conditions)
                 log_warning("%s: No valid settings found in the [Match] section. "
                             "The file will match all interfaces. "
                             "If that is intended, please add Name=* in the [Match] section.",
@@ -507,6 +508,7 @@ static Network *network_free(Network *network) {
         strv_free(network->match_driver);
         strv_free(network->match_type);
         strv_free(network->match_name);
+        strv_free(network->match_property);
         condition_free_list(network->conditions);
 
         free(network->description);
@@ -607,26 +609,16 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
 int network_get(Manager *manager, sd_device *device,
                 const char *ifname, const struct ether_addr *address,
                 Network **ret) {
-        const char *path = NULL, *driver = NULL, *devtype = NULL;
         Network *network;
         Iterator i;
 
         assert(manager);
         assert(ret);
 
-        if (device) {
-                (void) sd_device_get_property_value(device, "ID_PATH", &path);
-
-                (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
-
-                (void) sd_device_get_devtype(device, &devtype);
-        }
-
         ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
-                if (net_match_config(network->match_mac, network->match_path,
-                                     network->match_driver, network->match_type,
-                                     network->match_name,
-                                     address, path, driver, devtype, ifname)) {
+                if (net_match_config(network->match_mac, network->match_path, network->match_driver,
+                                     network->match_type, network->match_name, network->match_property,
+                                     device, address, ifname)) {
                         if (network->match_name && device) {
                                 const char *attr;
                                 uint8_t name_assign_type = NET_NAME_UNKNOWN;
@@ -701,7 +693,8 @@ int config_parse_stacked_netdev(const char *unit,
         assert(IN_SET(kind,
                       NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
                       NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
-                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
+                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
+                      NETDEV_KIND_XFRM));
 
         if (!ifname_valid(rvalue)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -811,110 +804,6 @@ int config_parse_domains(
         return 0;
 }
 
-int config_parse_ipv4ll(
-                const char* unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        AddressFamilyBoolean *link_local = data;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        /* Note that this is mostly like
-         * config_parse_address_family_boolean(), except that it
-         * applies only to IPv4 */
-
-        r = parse_boolean(rvalue);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to parse %s=%s, ignoring assignment. "
-                           "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
-                           lvalue, rvalue, lvalue);
-                return 0;
-        }
-
-        SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
-
-        log_syntax(unit, LOG_WARNING, filename, line, 0,
-                   "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
-                   lvalue, rvalue, address_family_boolean_to_string(*link_local));
-
-        return 0;
-}
-
-int config_parse_dhcp(
-                const char* unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        AddressFamilyBoolean *dhcp = data, s;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        /* Note that this is mostly like
-         * config_parse_address_family_boolean(), except that it
-         * understands some old names for the enum values */
-
-        s = address_family_boolean_from_string(rvalue);
-        if (s < 0) {
-
-                /* Previously, we had a slightly different enum here,
-                 * support its values for compatibility. */
-
-                if (streq(rvalue, "none"))
-                        s = ADDRESS_FAMILY_NO;
-                else if (streq(rvalue, "v4"))
-                        s = ADDRESS_FAMILY_IPV4;
-                else if (streq(rvalue, "v6"))
-                        s = ADDRESS_FAMILY_IPV6;
-                else if (streq(rvalue, "both"))
-                        s = ADDRESS_FAMILY_YES;
-                else {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse DHCP option, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "DHCP=%s is deprecated, please use DHCP=%s instead.",
-                           rvalue, address_family_boolean_to_string(s));
-        }
-
-        *dhcp = s;
-        return 0;
-}
-
-static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
-        [DHCP_CLIENT_ID_MAC] = "mac",
-        [DHCP_CLIENT_ID_DUID] = "duid",
-        [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
-                         "Failed to parse client identifier type");
-
 int config_parse_ipv6token(
                 const char* unit,
                 const char *filename,
@@ -1095,220 +984,6 @@ int config_parse_timezone(
         return free_and_replace(*datap, tz);
 }
 
-int config_parse_dhcp_server_dns(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *n = data;
-        const char *p = rvalue;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        for (;;) {
-                _cleanup_free_ char *w = NULL;
-                union in_addr_union a;
-                struct in_addr *m;
-
-                r = extract_first_word(&p, &w, NULL, 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to extract word, ignoring: %s", rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        break;
-
-                r = in_addr_from_string(AF_INET, w, &a);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
-                        continue;
-                }
-
-                m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
-                if (!m)
-                        return log_oom();
-
-                m[n->n_dhcp_server_dns++] = a.in;
-                n->dhcp_server_dns = m;
-        }
-
-        return 0;
-}
-
-int config_parse_radv_dns(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *n = data;
-        const char *p = rvalue;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        for (;;) {
-                _cleanup_free_ char *w = NULL;
-                union in_addr_union a;
-
-                r = extract_first_word(&p, &w, NULL, 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to extract word, ignoring: %s", rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        break;
-
-                if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
-                        struct in6_addr *m;
-
-                        m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
-                        if (!m)
-                                return log_oom();
-
-                        m[n->n_router_dns++] = a.in6;
-                        n->router_dns = m;
-
-                } else
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse DNS server address, ignoring: %s", w);
-        }
-
-        return 0;
-}
-
-int config_parse_radv_search_domains(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *n = data;
-        const char *p = rvalue;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        for (;;) {
-                _cleanup_free_ char *w = NULL, *idna = NULL;
-
-                r = extract_first_word(&p, &w, NULL, 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to extract word, ignoring: %s", rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        break;
-
-                r = dns_name_apply_idna(w, &idna);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
-                        continue;
-                } else if (r == 0)
-                        /* transfer ownership to simplify subsequent operations */
-                        idna = TAKE_PTR(w);
-
-                r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
-                if (r < 0)
-                        return r;
-
-                r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
-                if (r < 0)
-                        return r;
-        }
-
-        return 0;
-}
-
-int config_parse_dhcp_server_ntp(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *n = data;
-        const char *p = rvalue;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-
-        for (;;) {
-                _cleanup_free_ char *w = NULL;
-                union in_addr_union a;
-                struct in_addr *m;
-
-                r = extract_first_word(&p, &w, NULL, 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to extract word, ignoring: %s", rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        return 0;
-
-                r = in_addr_from_string(AF_INET, w, &a);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to parse NTP server address '%s', ignoring: %m", w);
-                        continue;
-                }
-
-                m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
-                if (!m)
-                        return log_oom();
-
-                m[n->n_dhcp_server_ntp++] = a.in;
-                n->dhcp_server_ntp = m;
-        }
-}
-
 int config_parse_dns(
                 const char *unit,
                 const char *filename,
@@ -1485,250 +1160,6 @@ int config_parse_ntp(
         return 0;
 }
 
-int config_parse_dhcp_user_class(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        char ***l = data;
-        int r;
-
-        assert(l);
-        assert(lvalue);
-        assert(rvalue);
-
-        if (isempty(rvalue)) {
-                *l = strv_free(*l);
-                return 0;
-        }
-
-        for (;;) {
-                _cleanup_free_ char *w = NULL;
-
-                r = extract_first_word(&rvalue, &w, NULL, 0);
-                if (r == -ENOMEM)
-                        return log_oom();
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to split user classes option, ignoring: %s", rvalue);
-                        break;
-                }
-                if (r == 0)
-                        break;
-
-                if (strlen(w) > 255) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "%s length is not in the range 1-255, ignoring.", w);
-                        continue;
-                }
-
-                r = strv_push(l, w);
-                if (r < 0)
-                        return log_oom();
-
-                w = NULL;
-        }
-
-        return 0;
-}
-
-int config_parse_section_route_table(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *network = data;
-        uint32_t rt;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = safe_atou32(rvalue, &rt);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
-                return 0;
-        }
-
-        if (streq_ptr(section, "DHCP")) {
-                network->dhcp_route_table = rt;
-                network->dhcp_route_table_set = true;
-        } else { /* section is IPv6AcceptRA */
-                network->ipv6_accept_ra_route_table = rt;
-                network->ipv6_accept_ra_route_table_set = true;
-        }
-
-        return 0;
-}
-
-int config_parse_dhcp_max_attempts(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *network = data;
-        uint64_t a;
-        int r;
-
-        assert(network);
-        assert(lvalue);
-        assert(rvalue);
-
-        if (isempty(rvalue)) {
-                network->dhcp_max_attempts = 0;
-                return 0;
-        }
-
-        if (streq(rvalue, "infinity")) {
-                network->dhcp_max_attempts = (uint64_t) -1;
-                return 0;
-        }
-
-        r = safe_atou64(rvalue, &a);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
-                return 0;
-        }
-
-        if (a == 0) {
-                log_syntax(unit, LOG_ERR, filename, line, 0,
-                           "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
-                return 0;
-        }
-
-        network->dhcp_max_attempts = a;
-
-        return 0;
-}
-
-int config_parse_dhcp_black_listed_ip_address(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *network = data;
-        const char *p;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        if (isempty(rvalue)) {
-                network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
-                return 0;
-        }
-
-        for (p = rvalue;;) {
-                _cleanup_free_ char *n = NULL;
-                union in_addr_union ip;
-
-                r = extract_first_word(&p, &n, NULL, 0);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
-                                   rvalue);
-                        return 0;
-                }
-                if (r == 0)
-                        return 0;
-
-                r = in_addr_from_string(AF_INET, n, &ip);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
-                        continue;
-                }
-
-                r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
-                if (r < 0)
-                        return log_oom();
-
-                r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
-                if (r < 0)
-                        log_syntax(unit, LOG_ERR, filename, line, r,
-                                   "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
-        }
-
-        return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
-                         "Failed to parse DHCP use domains setting");
-
-static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
-        [DHCP_USE_DOMAINS_NO] = "no",
-        [DHCP_USE_DOMAINS_ROUTE] = "route",
-        [DHCP_USE_DOMAINS_YES] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
-
-int config_parse_iaid(const char *unit,
-                      const char *filename,
-                      unsigned line,
-                      const char *section,
-                      unsigned section_line,
-                      const char *lvalue,
-                      int ltype,
-                      const char *rvalue,
-                      void *data,
-                      void *userdata) {
-        Network *network = data;
-        uint32_t iaid;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(network);
-
-        r = safe_atou32(rvalue, &iaid);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Unable to read IAID, ignoring assignment: %s", rvalue);
-                return 0;
-        }
-
-        network->iaid = iaid;
-        network->iaid_set = true;
-
-        return 0;
-}
-
 int config_parse_required_for_online(
                 const char *unit,
                 const char *filename,
index 7b92a5442666930c01476f89844e743f580ba58e..a16ec7413132332601bd9ae340fded3a5d226b21 100644 (file)
@@ -6,13 +6,14 @@
 
 #include "condition.h"
 #include "conf-parser.h"
-#include "dhcp-identifier.h"
 #include "hashmap.h"
 #include "netdev/bridge.h"
 #include "netdev/netdev.h"
 #include "networkd-address-label.h"
 #include "networkd-address.h"
 #include "networkd-brvlan.h"
+#include "networkd-dhcp-common.h"
+#include "networkd-dhcp4.h"
 #include "networkd-fdb.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-lldp-rx.h"
 #include "ordered-set.h"
 #include "resolve-util.h"
 
-#define DHCP_ROUTE_METRIC 1024
-#define IPV4LL_ROUTE_METRIC 2048
-
-#define BRIDGE_VLAN_BITMAP_MAX 4096
-#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
-
-typedef enum DHCPClientIdentifier {
-        DHCP_CLIENT_ID_MAC,
-        DHCP_CLIENT_ID_DUID,
-        /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
-         * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
-         * requires the client id to be set to a custom string, reported at
-         * https://github.com/systemd/systemd/issues/7828 */
-        DHCP_CLIENT_ID_DUID_ONLY,
-        _DHCP_CLIENT_ID_MAX,
-        _DHCP_CLIENT_ID_INVALID = -1,
-} DHCPClientIdentifier;
-
 typedef enum IPv6PrivacyExtensions {
         /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
         IPV6_PRIVACY_EXTENSIONS_NO,
@@ -52,32 +35,6 @@ typedef enum IPv6PrivacyExtensions {
         _IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
 } IPv6PrivacyExtensions;
 
-typedef enum DHCPUseDomains {
-        DHCP_USE_DOMAINS_NO,
-        DHCP_USE_DOMAINS_YES,
-        DHCP_USE_DOMAINS_ROUTE,
-        _DHCP_USE_DOMAINS_MAX,
-        _DHCP_USE_DOMAINS_INVALID = -1,
-} DHCPUseDomains;
-
-typedef struct DUID {
-        /* Value of Type in [DHCP] section */
-        DUIDType type;
-
-        uint8_t raw_data_len;
-        uint8_t raw_data[MAX_DUID_LEN];
-        usec_t llt_time;
-} DUID;
-
-typedef enum RADVPrefixDelegation {
-        RADV_PREFIX_DELEGATION_NONE,
-        RADV_PREFIX_DELEGATION_STATIC,
-        RADV_PREFIX_DELEGATION_DHCP6,
-        RADV_PREFIX_DELEGATION_BOTH,
-        _RADV_PREFIX_DELEGATION_MAX,
-        _RADV_PREFIX_DELEGATION_INVALID = -1,
-} RADVPrefixDelegation;
-
 typedef enum KeepConfiguration {
         KEEP_CONFIGURATION_NO            = 0,
         KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0,
@@ -104,6 +61,7 @@ struct Network {
         char **match_driver;
         char **match_type;
         char **match_name;
+        char **match_property;
         LIST_HEAD(Condition, conditions);
 
         char *description;
@@ -111,6 +69,7 @@ struct Network {
         NetDev *bridge;
         NetDev *bond;
         NetDev *vrf;
+        NetDev *xfrm;
         Hashmap *stacked_netdevs;
         char *bridge_name;
         char *bond_name;
@@ -308,47 +267,22 @@ void network_apply_anonymize_if_set(Network *network);
 bool network_has_static_ipv6_addresses(Network *network);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev);
-CONFIG_PARSER_PROTOTYPE(config_parse_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
-CONFIG_PARSER_PROTOTYPE(config_parse_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
+CONFIG_PARSER_PROTOTYPE(config_parse_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
 CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
-CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
 CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
-CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
 CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
 CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
-/* Legacy IPv4LL support */
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
 
 const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
 
-extern const sd_bus_vtable network_vtable[];
-
-int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
-int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
-
 const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
 IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
 
-const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
-DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
-
-const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
-RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
-
 const char* keep_configuration_to_string(KeepConfiguration i) _const_;
 KeepConfiguration keep_configuration_from_string(const char *s) _pure_;
index fdbf7cac62880f7105bfe5ca4e2b8576bf6d9ea6..25321aefed3a598432054faef7b41793c3b02b28 100644 (file)
@@ -6,6 +6,7 @@
 #include <netinet/icmp6.h>
 #include <arpa/inet.h>
 
+#include "dns-domain.h"
 #include "networkd-address.h"
 #include "networkd-manager.h"
 #include "networkd-radv.h"
 #include "string-table.h"
 #include "strv.h"
 
-static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
-        [RADV_PREFIX_DELEGATION_NONE] = "no",
-        [RADV_PREFIX_DELEGATION_STATIC] = "static",
-        [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
-        [RADV_PREFIX_DELEGATION_BOTH] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
-                radv_prefix_delegation,
-                RADVPrefixDelegation,
-                RADV_PREFIX_DELEGATION_BOTH);
-
-int config_parse_router_prefix_delegation(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                const char *section,
-                unsigned section_line,
-                const char *lvalue,
-                int ltype,
-                const char *rvalue,
-                void *data,
-                void *userdata) {
-
-        Network *network = userdata;
-        RADVPrefixDelegation d;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        d = radv_prefix_delegation_from_string(rvalue);
-        if (d < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue);
-                return 0;
-        }
-
-        network->router_prefix_delegation = d;
-
-        return 0;
-}
-
-int config_parse_router_preference(const char *unit,
-                                   const char *filename,
-                                   unsigned line,
-                                   const char *section,
-                                   unsigned section_line,
-                                   const char *lvalue,
-                                   int ltype,
-                                   const char *rvalue,
-                                   void *data,
-                                   void *userdata) {
-        Network *network = userdata;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        if (streq(rvalue, "high"))
-                network->router_preference = SD_NDISC_PREFERENCE_HIGH;
-        else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
-                network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
-        else if (streq(rvalue, "low"))
-                network->router_preference = SD_NDISC_PREFERENCE_LOW;
-        else
-                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue);
-
-        return 0;
-}
-
 void prefix_free(Prefix *prefix) {
         if (!prefix)
                 return;
@@ -515,3 +442,185 @@ int radv_configure(Link *link) {
 
         return radv_emit_dns(link);
 }
+
+int config_parse_radv_dns(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *n = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+                union in_addr_union a;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract word, ignoring: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
+
+                if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
+                        struct in6_addr *m;
+
+                        m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
+                        if (!m)
+                                return log_oom();
+
+                        m[n->n_router_dns++] = a.in6;
+                        n->router_dns = m;
+
+                } else
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Failed to parse DNS server address, ignoring: %s", w);
+        }
+
+        return 0;
+}
+
+int config_parse_radv_search_domains(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *n = data;
+        const char *p = rvalue;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL, *idna = NULL;
+
+                r = extract_first_word(&p, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to extract word, ignoring: %s", rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        break;
+
+                r = dns_name_apply_idna(w, &idna);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
+                        continue;
+                } else if (r == 0)
+                        /* transfer ownership to simplify subsequent operations */
+                        idna = TAKE_PTR(w);
+
+                r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
+                if (r < 0)
+                        return r;
+
+                r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
+        [RADV_PREFIX_DELEGATION_NONE] = "no",
+        [RADV_PREFIX_DELEGATION_STATIC] = "static",
+        [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
+        [RADV_PREFIX_DELEGATION_BOTH] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
+                radv_prefix_delegation,
+                RADVPrefixDelegation,
+                RADV_PREFIX_DELEGATION_BOTH);
+
+int config_parse_router_prefix_delegation(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Network *network = userdata;
+        RADVPrefixDelegation d;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        d = radv_prefix_delegation_from_string(rvalue);
+        if (d < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue);
+                return 0;
+        }
+
+        network->router_prefix_delegation = d;
+
+        return 0;
+}
+
+int config_parse_router_preference(const char *unit,
+                                   const char *filename,
+                                   unsigned line,
+                                   const char *section,
+                                   unsigned section_line,
+                                   const char *lvalue,
+                                   int ltype,
+                                   const char *rvalue,
+                                   void *data,
+                                   void *userdata) {
+        Network *network = userdata;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "high"))
+                network->router_preference = SD_NDISC_PREFERENCE_HIGH;
+        else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
+                network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
+        else if (streq(rvalue, "low"))
+                network->router_preference = SD_NDISC_PREFERENCE_LOW;
+        else
+                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue);
+
+        return 0;
+}
index 3192bb8b6c8db04cd64c03be46f2186af07c9e17..45be083bfefec928bd51cd6aa144ad32ac0187ac 100644 (file)
 
 typedef struct Prefix Prefix;
 
+typedef enum RADVPrefixDelegation {
+        RADV_PREFIX_DELEGATION_NONE,
+        RADV_PREFIX_DELEGATION_STATIC,
+        RADV_PREFIX_DELEGATION_DHCP6,
+        RADV_PREFIX_DELEGATION_BOTH,
+        _RADV_PREFIX_DELEGATION_MAX,
+        _RADV_PREFIX_DELEGATION_INVALID = -1,
+} RADVPrefixDelegation;
+
 struct Prefix {
         Network *network;
         NetworkConfigSection *section;
@@ -26,11 +35,16 @@ void prefix_free(Prefix *prefix);
 
 DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
 
+int radv_emit_dns(Link *link);
+int radv_configure(Link *link);
+
+const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
+RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
 CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
 CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
-
-int radv_emit_dns(Link *link);
-int radv_configure(Link *link);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
index cd31548f94e3dca8aabf07f6f9009c778f0018b5..f79d5b2057071560cd4157e73418217581de6148 100644 (file)
@@ -7,6 +7,7 @@
 #include "in-addr-util.h"
 #include "missing_network.h"
 #include "netlink-util.h"
+#include "networkd-ipv4ll.h"
 #include "networkd-manager.h"
 #include "networkd-route.h"
 #include "parse-util.h"
index dfb41f801b359d1b65063cc57e06b9c6ef6967a6..07ca127654ff8ac36f3b399f278e52e821885694 100644 (file)
@@ -174,7 +174,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
         assert_se(network = new0(Network, 1));
         network->n_ref = 1;
         assert_se(network->filename = strdup("hogehoge.network"));
-        assert_se(config_parse_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
+        assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
         assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
         assert_se(network->n_static_addresses == 1);
         assert_se(network_verify(network) >= 0);
@@ -215,6 +215,27 @@ static void test_config_parse_address(void) {
         test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0);
 }
 
+static void test_config_parse_match_ifnames(void) {
+        _cleanup_strv_free_ char **names = NULL;
+
+        assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
+        assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0);
+        assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "aaa bbb ccc", &names, NULL) == 0);
+
+        strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc"));
+}
+
+static void test_config_parse_match_strv(void) {
+        _cleanup_strv_free_ char **names = NULL;
+
+        assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
+        assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0);
+        assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0,
+                                          "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"", &names, NULL) == 0);
+
+        strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "KEY=val", "KEY2=val with space", "KEY3=val with \"quotation\""));
+}
+
 int main(int argc, char **argv) {
         log_parse_environment();
         log_open();
@@ -223,6 +244,8 @@ int main(int argc, char **argv) {
         test_config_parse_duid_rawdata();
         test_config_parse_hwaddr();
         test_config_parse_address();
+        test_config_parse_match_ifnames();
+        test_config_parse_match_strv();
 
         return 0;
 }
index 7ada4116368b5c9c904f66c41049a9f8544d9dba..a563c026dd6edb9646c876002c94f21b27d22c0c 100644 (file)
@@ -2798,7 +2798,6 @@ static int inner_child(
                 int master_pty_socket,
                 FDSet *fds) {
 
-        _cleanup_close_ int master = -1;
         _cleanup_free_ char *home = NULL;
         char as_uuid[37];
         size_t n_env = 1;
@@ -2931,6 +2930,7 @@ static int inner_child(
         }
 
         if (arg_console_mode != CONSOLE_PIPE) {
+                _cleanup_close_ int master = -1;
                 _cleanup_free_ char *console = NULL;
 
                 /* Allocate a pty and make it available as /dev/console. */
index ce86f96e13dd96d622b25e67f500983c3df6c329..9e7178ac45897ed95da7aea93d3f56694d1c2b82 100644 (file)
@@ -129,7 +129,8 @@ static int maybe_resize_slave_device(const char *mountpath, dev_t main_devno) {
 
 #if HAVE_LIBCRYPTSETUP
         crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL);
-        crypt_set_debug_level(1);
+        if (DEBUG_LOGGING)
+                crypt_set_debug_level(CRYPT_DEBUG_ALL);
 #endif
 
         r = get_block_device_harder(mountpath, &devno);
index 5464360f894cc9eb37c3926dcbcc000b85c77c50..c74ec429627b721a6b8d85d857437d5eea2cbf2e 100644 (file)
@@ -134,10 +134,8 @@ static int run(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (argc != 1) {
-                log_error("This program takes no arguments.");
-                return -EINVAL;
-        }
+        if (argc != 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0);
 
index f8f6c2d3ec12573c2a10d399ed42644009721323..455788a1840c712bc8fc8a60554de6f6ea838321 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/un.h>
 
 #include "alloc-util.h"
+#include "main-func.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "log.h"
@@ -34,66 +35,49 @@ static int send_on_socket(int fd, const char *socket_name, const void *packet, s
         return 0;
 }
 
-int main(int argc, char *argv[]) {
-        _cleanup_free_ char *packet = NULL;
+static int run(int argc, char *argv[]) {
+        _cleanup_(erase_and_freep) char *packet = NULL;
         _cleanup_close_ int fd = -1;
         size_t length = 0;
         int r;
 
         log_setup_service();
 
-        if (argc != 3) {
-                log_error("Wrong number of arguments.");
-                return EXIT_FAILURE;
-        }
+        if (argc != 3)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
 
         if (streq(argv[1], "1")) {
                 _cleanup_string_free_erase_ char *line = NULL;
 
                 r = read_line(stdin, LONG_LINE_MAX, &line);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to read password: %m");
-                        goto finish;
-                }
-                if (r == 0) {
-                        log_error("Got EOF while reading password.");
-                        r = -EIO;
-                        goto finish;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to read password: %m");
+                if (r == 0)
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
+                                               "Got EOF while reading password.");
 
                 packet = strjoin("+", line);
-                if (!packet) {
-                        r = log_oom();
-                        goto finish;
-                }
+                if (!packet)
+                        return log_oom();
 
                 length = 1 + strlen(line) + 1;
 
         } else if (streq(argv[1], "0")) {
                 packet = strdup("-");
-                if (!packet) {
-                        r = log_oom();
-                        goto finish;
-                }
+                if (!packet)
+                        return log_oom();
 
                 length = 1;
 
-        } else {
-                log_error("Invalid first argument %s", argv[1]);
-                r = -EINVAL;
-                goto finish;
-        }
+        } else
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Invalid first argument %s", argv[1]);
 
         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
-        if (fd < 0) {
-                r = log_error_errno(errno, "socket() failed: %m");
-                goto finish;
-        }
+        if (fd < 0)
+                return log_error_errno(errno, "socket() failed: %m");
 
-        r = send_on_socket(fd, argv[2], packet, length);
-
-finish:
-        explicit_bzero_safe(packet, length);
-
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return send_on_socket(fd, argv[2], packet, length);
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 05c1552a8b7ff74bb36aa8b5c7d9e9c413133c61..c11b7f57ffa154f334f3ecf05df87a199a51819c 100644 (file)
@@ -1266,8 +1266,8 @@ static int start_transient_service(
                         else if (c.exit_code > 0)
                                 log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
 
-                        if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY &&
-                            c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY &&
+                        if (timestamp_is_set(c.inactive_enter_usec) &&
+                            timestamp_is_set(c.inactive_exit_usec) &&
                             c.inactive_enter_usec > c.inactive_exit_usec) {
                                 char ts[FORMAT_TIMESPAN_MAX];
                                 log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
index 6c0a36990291832e7c2c36953515c5ecb91448c2..00c41a0382082bc585e14698a9a61636846669b7 100644 (file)
@@ -63,13 +63,16 @@ static int lookup_key(const char *keyname, key_serial_t *ret) {
 }
 
 static int retrieve_key(key_serial_t serial, char ***ret) {
-        _cleanup_free_ char *p = NULL;
-        long m = 100, n;
+        size_t nfinal, m = 100;
         char **l;
+        _cleanup_(erase_and_freep) char *pfinal = NULL;
 
         assert(ret);
 
         for (;;) {
+                _cleanup_(erase_and_freep) char *p = NULL;
+                long n;
+
                 p = new(char, m);
                 if (!p)
                         return -ENOMEM;
@@ -77,33 +80,28 @@ static int retrieve_key(key_serial_t serial, char ***ret) {
                 n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
                 if (n < 0)
                         return -errno;
-                if (n < m)
+                if ((size_t) n < m) {
+                        nfinal = (size_t) n;
+                        pfinal = TAKE_PTR(p);
                         break;
-
-                explicit_bzero_safe(p, m);
+                }
 
                 if (m > LONG_MAX / 2) /* overflow check */
                         return -ENOMEM;
                 m *= 2;
-                if ((long) (size_t) m != m) /* make sure that this still fits if converted to size_t */
-                        return -ENOMEM;
-
-                free(p);
         }
 
-        l = strv_parse_nulstr(p, n);
+        l = strv_parse_nulstr(pfinal, nfinal);
         if (!l)
                 return -ENOMEM;
 
-        explicit_bzero_safe(p, n);
-
         *ret = l;
         return 0;
 }
 
 static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) {
         _cleanup_strv_free_erase_ char **l = NULL;
-        _cleanup_free_ char *p = NULL;
+        _cleanup_(erase_and_freep) char *p = NULL;
         key_serial_t serial;
         size_t n;
         int r;
@@ -131,7 +129,6 @@ static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **pa
                 return r;
 
         serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING);
-        explicit_bzero_safe(p, n);
         if (serial == -1)
                 return -errno;
 
index f930c026735ddd5aa7e49a0463c83f11dd3a171e..030e12e4ee2e688aa07167838348b26973491e32 100644 (file)
@@ -19,6 +19,7 @@
 #include "device-nodes.h"
 #include "device-util.h"
 #include "dissect-image.h"
+#include "dm-util.h"
 #include "env-file.h"
 #include "fd-util.h"
 #include "fileio.h"
@@ -1225,40 +1226,6 @@ int dissected_image_decrypt_interactively(
         }
 }
 
-#if HAVE_LIBCRYPTSETUP
-static int deferred_remove(DecryptedPartition *p) {
-        struct dm_ioctl dm = {
-                .version = {
-                        DM_VERSION_MAJOR,
-                        DM_VERSION_MINOR,
-                        DM_VERSION_PATCHLEVEL
-                },
-                .data_size = sizeof(dm),
-                .flags = DM_DEFERRED_REMOVE,
-        };
-
-        _cleanup_close_ int fd = -1;
-
-        assert(p);
-
-        /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
-
-        fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
-        if (fd < 0)
-                return -errno;
-
-        if (strlen(p->name) > sizeof(dm.name))
-                return -ENAMETOOLONG;
-
-        strncpy(dm.name, p->name, sizeof(dm.name));
-
-        if (ioctl(fd, DM_DEV_REMOVE, &dm))
-                return -errno;
-
-        return 0;
-}
-#endif
-
 int decrypted_image_relinquish(DecryptedImage *d) {
 
 #if HAVE_LIBCRYPTSETUP
@@ -1278,7 +1245,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
                 if (p->relinquished)
                         continue;
 
-                r = deferred_remove(p);
+                r = dm_deferred_remove(p->name);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);
 
diff --git a/src/shared/dm-util.c b/src/shared/dm-util.c
new file mode 100644 (file)
index 0000000..f73bf93
--- /dev/null
@@ -0,0 +1,42 @@
+#include <fcntl.h>
+#include <linux/dm-ioctl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "dm-util.h"
+#include "fd-util.h"
+#include "string-util.h"
+
+int dm_deferred_remove(const char *name) {
+
+        struct dm_ioctl dm = {
+                .version = {
+                        DM_VERSION_MAJOR,
+                        DM_VERSION_MINOR,
+                        DM_VERSION_PATCHLEVEL
+                },
+                .data_size = sizeof(dm),
+                .flags = DM_DEFERRED_REMOVE,
+        };
+
+        _cleanup_close_ int fd = -1;
+
+        assert(name);
+
+        /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl()
+         * directly. */
+
+        if (strlen(name) >= sizeof(dm.name))
+                return -ENODEV; /* A device with a name longer than this cannot possibly exist */
+
+        fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
+        if (fd < 0)
+                return -errno;
+
+        strncpy_exact(dm.name, name, sizeof(dm.name));
+
+        if (ioctl(fd, DM_DEV_REMOVE, &dm))
+                return -errno;
+
+        return 0;
+}
diff --git a/src/shared/dm-util.h b/src/shared/dm-util.h
new file mode 100644 (file)
index 0000000..6c78bfe
--- /dev/null
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int dm_deferred_remove(const char *name);
index 1346da9323d8585173ee5744ab2b05e5aaceae70..fad129794d2fa52088c1329edc3bb9c1820f3aa3 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "sd-id128.h"
 
+#include "efi/loader-features.h"
 #include "time-util.h"
 
 #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
 #define EFI_VARIABLE_RUNTIME_ACCESS     0x0000000000000004
 
-#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT          (UINT64_C(1) << 0)
-#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1)
-#define EFI_LOADER_FEATURE_ENTRY_DEFAULT           (UINT64_C(1) << 2)
-#define EFI_LOADER_FEATURE_ENTRY_ONESHOT           (UINT64_C(1) << 3)
-#define EFI_LOADER_FEATURE_BOOT_COUNTING           (UINT64_C(1) << 4)
-
 #if ENABLE_EFI
 
 bool is_efi_boot(void);
index 87bc3f76fedd29b31feb58b1d28f11fd255f942d..93bdd8c7f1241ebba44a4052fd45c47f3b98d6a2 100644 (file)
@@ -90,6 +90,7 @@ int fw_add_masquerade(
                 const union in_addr_union *destination,
                 unsigned destination_prefixlen) {
 
+        static const xt_chainlabel chain = "POSTROUTING";
         _cleanup_(iptc_freep) struct xtc_handle *h = NULL;
         struct ipt_entry *entry, *mask;
         struct ipt_entry_target *t;
@@ -133,15 +134,15 @@ int fw_add_masquerade(
         memset(mask, 0xFF, sz);
 
         if (add) {
-                if (iptc_check_entry("POSTROUTING", entry, (unsigned char*) mask, h))
+                if (iptc_check_entry(chain, entry, (unsigned char*) mask, h))
                         return 0;
                 if (errno != ENOENT) /* if other error than not existing yet, fail */
                         return -errno;
 
-                if (!iptc_insert_entry("POSTROUTING", entry, 0, h))
+                if (!iptc_insert_entry(chain, entry, 0, h))
                         return -errno;
         } else {
-                if (!iptc_delete_entry("POSTROUTING", entry, (unsigned char*) mask, h)) {
+                if (!iptc_delete_entry(chain, entry, (unsigned char*) mask, h)) {
                         if (errno == ENOENT) /* if it's already gone, all is good! */
                                 return 0;
 
@@ -169,6 +170,7 @@ int fw_add_local_dnat(
                 uint16_t remote_port,
                 const union in_addr_union *previous_remote) {
 
+        static const xt_chainlabel chain_pre = "PREROUTING", chain_output = "OUTPUT";
         _cleanup_(iptc_freep) struct xtc_handle *h = NULL;
         struct ipt_entry *entry, *mask;
         struct ipt_entry_target *t;
@@ -275,11 +277,11 @@ int fw_add_local_dnat(
 
         if (add) {
                 /* Add the PREROUTING rule, if it is missing so far */
-                if (!iptc_check_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+                if (!iptc_check_entry(chain_pre, entry, (unsigned char*) mask, h)) {
                         if (errno != ENOENT)
                                 return -EINVAL;
 
-                        if (!iptc_insert_entry("PREROUTING", entry, 0, h))
+                        if (!iptc_insert_entry(chain_pre, entry, 0, h))
                                 return -errno;
                 }
 
@@ -287,7 +289,7 @@ int fw_add_local_dnat(
                 if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
                         mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
 
-                        if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+                        if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
                                 if (errno != ENOENT)
                                         return -errno;
                         }
@@ -305,11 +307,11 @@ int fw_add_local_dnat(
                                 entry->ip.invflags = IPT_INV_DSTIP;
                         }
 
-                        if (!iptc_check_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+                        if (!iptc_check_entry(chain_output, entry, (unsigned char*) mask, h)) {
                                 if (errno != ENOENT)
                                         return -errno;
 
-                                if (!iptc_insert_entry("OUTPUT", entry, 0, h))
+                                if (!iptc_insert_entry(chain_output, entry, 0, h))
                                         return -errno;
                         }
 
@@ -317,14 +319,14 @@ int fw_add_local_dnat(
                         if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
                                 mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
 
-                                if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+                                if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
                                         if (errno != ENOENT)
                                                 return -errno;
                                 }
                         }
                 }
         } else {
-                if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+                if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
                         if (errno != ENOENT)
                                 return -errno;
                 }
@@ -336,7 +338,7 @@ int fw_add_local_dnat(
                                 entry->ip.invflags = IPT_INV_DSTIP;
                         }
 
-                        if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+                        if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
                                 if (errno != ENOENT)
                                         return -errno;
                         }
diff --git a/src/shared/fsck-util.h b/src/shared/fsck-util.h
new file mode 100644 (file)
index 0000000..78ec18d
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/* exit codes as defined in fsck(8) */
+enum {
+        FSCK_SUCCESS                 = 0,
+        FSCK_ERROR_CORRECTED         = 1 << 0,
+        FSCK_SYSTEM_SHOULD_REBOOT    = 1 << 1,
+        FSCK_ERRORS_LEFT_UNCORRECTED = 1 << 2,
+        FSCK_OPERATIONAL_ERROR       = 1 << 3,
+        FSCK_USAGE_OR_SYNTAX_ERROR   = 1 << 4,
+        FSCK_USER_CANCELLED          = 1 << 5,
+        FSCK_SHARED_LIB_ERROR        = 1 << 7,
+};
index 218fbe90572c1315ca4d5e8046769be155fc71af..44032548ad105bb312add30e0c95870202722e88 100644 (file)
@@ -4,6 +4,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "errno-util.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "io-util.h"
@@ -422,7 +423,7 @@ int journal_importer_push_data(JournalImporter *imp, const char *data, size_t si
                                        "Failed to store received data of size %zu "
                                        "(in addition to existing %zu bytes with %zu filled): %s",
                                        size, imp->size, imp->filled,
-                                       strerror(ENOMEM));
+                                       strerror_safe(ENOMEM));
 
         memcpy(imp->buf + imp->filled, data, size);
         imp->filled += size;
index baea31fed93bada63202267c7e54236ffcb0aa42..a068049b57f1863902ed9dec1665b6102ed3275d 100644 (file)
@@ -3407,7 +3407,7 @@ int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFla
 int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
         _cleanup_strv_free_ char **l = NULL;
         char ***s = userdata;
-        size_t i;
+        JsonVariant *e;
         int r;
 
         assert(variant);
@@ -3421,11 +3421,7 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
         if (!json_variant_is_array(variant))
                 return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name));
 
-        for (i = 0; i < json_variant_elements(variant); i++) {
-                JsonVariant *e;
-
-                assert_se(e = json_variant_by_index(variant, i));
-
+        JSON_VARIANT_ARRAY_FOREACH(e, variant) {
                 if (!json_variant_is_string(e))
                         return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string.");
 
index 59b50a754edeb23ad0206276e6d5e7fb1c9430b1..d2540320d8a6b696e97ce2cf97b863a669060a6f 100644 (file)
@@ -50,6 +50,8 @@ shared_sources = files('''
         dev-setup.h
         dissect-image.c
         dissect-image.h
+        dm-util.c
+        dm-util.h
         dns-domain.c
         dns-domain.h
         dropin.c
@@ -72,6 +74,7 @@ shared_sources = files('''
         firewall-util.h
         format-table.c
         format-table.h
+        fsck-util.h
         fstab-util.c
         fstab-util.h
         generator.c
index dea8e4363f2d20e6ef735fefb37594a30a33c47b..54d48991e855a6e2af209fdca76ac368f3d95de2 100644 (file)
@@ -1002,7 +1002,6 @@ int varlink_wait(Varlink *v, usec_t timeout) {
         usec_t t;
 
         assert_return(v, -EINVAL);
-        assert_return(!v->server, -ENOTTY);
 
         if (v->state == VARLINK_DISCONNECTED)
                 return -ENOTCONN;
@@ -2053,12 +2052,14 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
 
         varlink_set_state(v, VARLINK_IDLE_SERVER);
 
-        r = varlink_attach_event(v, server->event, server->event_priority);
-        if (r < 0) {
-                varlink_log_errno(v, r, "Failed to attach new connection: %m");
-                v->fd = -1; /* take the fd out of the connection again */
-                varlink_close(v);
-                return r;
+        if (server->event) {
+                r = varlink_attach_event(v, server->event, server->event_priority);
+                if (r < 0) {
+                        varlink_log_errno(v, r, "Failed to attach new connection: %m");
+                        v->fd = -1; /* take the fd out of the connection again */
+                        varlink_close(v);
+                        return r;
+                }
         }
 
         if (ret)
index 2f9df7dd1b74eb394a642aa33ed3c7803c6880c3..a4b42df85ba8fbd7698632a072796017f2f06c90 100644 (file)
@@ -22,6 +22,22 @@ int parse_vlanid(const char *p, uint16_t *ret) {
         return 0;
 }
 
+int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end) {
+        unsigned lower, upper;
+        int r;
+
+        r = parse_range(p, &lower, &upper);
+        if (r < 0)
+                return r;
+
+        if (lower > VLANID_MAX || upper > VLANID_MAX || lower > upper)
+                return -EINVAL;
+
+        *vid = lower;
+        *vid_end = upper;
+        return 0;
+}
+
 int config_parse_default_port_vlanid(
                 const char *unit,
                 const char *filename,
index ebe4331ed4fe226f9d5b306c0002450f41a45cad..c55adee3c07ab7487eb64e79d499db1123ad6658 100644 (file)
@@ -15,6 +15,7 @@ static inline bool vlanid_is_valid(uint16_t id) {
 }
 
 int parse_vlanid(const char *p, uint16_t *ret);
+int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid);
 CONFIG_PARSER_PROTOTYPE(config_parse_vlanid);
index dbe442d7da65702d8d1caa3e171f038261494d02..b7de010704864eae858c655066af21900da3c347 100644 (file)
@@ -1228,7 +1228,7 @@ static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
         assert(nw);
         assert(next);
 
-        if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
+        if (timestamp_is_set(next->monotonic)) {
                 usec_t converted;
 
                 if (next->monotonic > nw->monotonic)
@@ -1236,7 +1236,7 @@ static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
                 else
                         converted = nw->realtime - (nw->monotonic - next->monotonic);
 
-                if (next->realtime != USEC_INFINITY && next->realtime > 0)
+                if (timestamp_is_set(next->realtime))
                         next_elapse = MIN(converted, next->realtime);
                 else
                         next_elapse = converted;
@@ -2508,13 +2508,14 @@ static int unit_find_paths(
         int r;
 
         /**
-         * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is found, and
-         * sets:
+         * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is
+         * found, and sets:
          * - the path to the unit in *ret_frament_path, if it exists on disk,
-         * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins were found.
+         * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins
+         *   were found.
          *
-         * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for some
-         * reason (the latter only applies if we are going through the service manager)
+         * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for
+         * some reason (the latter only applies if we are going through the service manager).
          */
 
         assert(unit_name);
@@ -2549,7 +2550,7 @@ static int unit_find_paths(
                         r = 0;
                         goto not_found;
                 }
-                if (!streq(load_state, "loaded"))
+                if (!STR_IN_SET(load_state, "loaded", "bad-setting"))
                         return -EKEYREJECTED;
 
                 r = sd_bus_get_property_string(
@@ -4500,7 +4501,7 @@ static void print_status_info(
         if (i->status_text)
                 printf("   Status: \"%s\"\n", i->status_text);
         if (i->status_errno > 0)
-                printf("    Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
+                printf("    Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno));
 
         if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
                 char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
index 62b0f723c7a1a316c0d496822c5b29608645e87a..860961e2ba4c996c6c6beb7047d18a781f98b7bd 100644 (file)
@@ -260,7 +260,7 @@ int sd_notify(int unset_environment, const char *state);
 
      sd_notifyf(0, "STATUS=Failed to start up: %s\n"
                    "ERRNO=%i",
-                   strerror(errno),
+                   strerror_safe(errno),
                    errno);
 
   See sd_notifyf(3) for more information.
index d27e0ad2019cb9b5016404ab1e24d3c360777e3b..b0a51185e9c19fc8dfe9f8a7119fc2044e96b40f 100644 (file)
@@ -105,6 +105,7 @@ int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short typ
 int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data);
 int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data);
 int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type);
+int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type);
 int sd_netlink_message_exit_container(sd_netlink_message *m);
 
 int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);
index e6b6d96d5a91b393ba4b2e2de80535d0e76b542e..cf69436d262945d63a650089a1c5a16113df1fdd 100644 (file)
@@ -6,6 +6,7 @@
 #include "alloc-util.h"
 #include "macro.h"
 #include "memory-util.h"
+#include "random-util.h"
 #include "tests.h"
 
 static void test_alloca(void) {
@@ -132,6 +133,20 @@ static void test_cleanup_order(void) {
         log_debug("z: %p", &z);
 }
 
+static void test_auto_erase_memory(void) {
+        _cleanup_(erase_and_freep) uint8_t *p1, *p2;
+
+        assert_se(p1 = new(uint8_t, 1024));
+        assert_se(p2 = new(uint8_t, 1024));
+
+        genuine_random_bytes(p1, 1024, RANDOM_BLOCK);
+
+        /* before we exit the scope, do something with this data, so that the compiler won't optimize this away */
+        memcpy(p2, p1, 1024);
+        for (size_t i = 0; i < 1024; i++)
+                assert_se(p1[i] == p2[i]);
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
@@ -140,6 +155,7 @@ int main(int argc, char *argv[]) {
         test_memdup_multiply_and_greedy_realloc();
         test_bool_assign();
         test_cleanup_order();
+        test_auto_erase_memory();
 
         return 0;
 }
index 10c9f63b9b3213d5da6c899ae013178c06048758..46358ef9527824867183203f0b275626e8b3f617 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "alloc-util.h"
 #include "calendarspec.h"
+#include "errno-util.h"
 #include "string-util.h"
 #include "util.h"
 
@@ -23,7 +24,7 @@ static void test_one(const char *input, const char *output) {
 
         u = now(CLOCK_REALTIME);
         r = calendar_spec_next_usec(c, u, &u);
-        printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
+        printf("Next: %s\n", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof(buf), u));
         calendar_spec_free(c);
 
         assert_se(calendar_spec_from_string(p, &c) >= 0);
@@ -56,7 +57,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_
 
         u = after;
         r = calendar_spec_next_usec(c, after, &u);
-        printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u));
+        printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u));
         if (expect != (usec_t)-1)
                 assert_se(r >= 0 && u == expect);
         else
@@ -103,10 +104,10 @@ static void test_hourly_bug_4031(void) {
         assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0);
 
         printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n);
-        printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u);
+        printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u), u);
 
         assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0);
-        printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w);
+        printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(zaf, sizeof zaf, w), w);
 
         assert_se(n < u);
         assert_se(u <= n + USEC_PER_HOUR);
index 3e91c87eea45c089484c0c90805facd1eab7deec..90a8d5f36c6f5f12367fde6fba65ef2da3631365 100644 (file)
@@ -464,7 +464,7 @@ static void test_path_extract_filename_one(const char *input, const char *output
         int r;
 
         r = path_extract_filename(input, &k);
-        log_info("%s â†’ %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror(-r), strnull(output), strerror(-ret));
+        log_info("%s â†’ %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror_safe(r), strnull(output), strerror_safe(ret));
         assert_se(streq_ptr(k, output));
         assert_se(r == ret);
 }
index 2a23bf2384b0de32fc43360c7ce19aee3eb3ba7d..014b1aa7a2f0eea88d54564cb61b9748159408c5 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "errno-util.h"
 #include "fd-util.h"
 #include "log.h"
 #include "memory-util.h"
@@ -95,13 +96,13 @@ static void test_sleep(void) {
 
         log_info("/= running system =/");
         r = can_sleep("suspend");
-        log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+        log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
         r = can_sleep("hibernate");
-        log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+        log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
         r = can_sleep("hybrid-sleep");
-        log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+        log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
         r = can_sleep("suspend-then-hibernate");
-        log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+        log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
 }
 
 int main(int argc, char* argv[]) {
index 21d56d9be68aae0704565b6ba6d8ca73b170f739..d7199124a3d9ed246ce173a2d392fc2ea5edf4a7 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <stdio.h>
 #include <string.h>
 
 #include "string-util.h"
@@ -78,6 +79,24 @@ static void test_strscpyl(void) {
         assert_se(space_left == 10);
 }
 
+static void test_sd_event_code_migration(void) {
+        char b[100 * DECIMAL_STR_MAX(unsigned) + 1];
+        char c[100 * DECIMAL_STR_MAX(unsigned) + 1], *p;
+        unsigned i;
+        size_t l;
+        int o;
+
+        for (i = o = 0; i < 100; i++)
+                o += snprintf(&b[o], sizeof(b) - o, "%u ", i);
+
+        p = c;
+        l = sizeof(c);
+        for (i = 0; i < 100; i++)
+                l = strpcpyf(&p, l, "%u ", i);
+
+        assert_se(streq(b, c));
+}
+
 int main(int argc, char *argv[]) {
         test_strpcpy();
         test_strpcpyf();
@@ -85,5 +104,7 @@ int main(int argc, char *argv[]) {
         test_strscpy();
         test_strscpyl();
 
+        test_sd_event_code_migration();
+
         return 0;
 }
index b8ee856a1593414793d57622e564d4d72cb1c6d0..ef817fca4f7024157003c39b7e17d403ad72573d 100644 (file)
@@ -2478,8 +2478,7 @@ static int patch_var_run(const char *fname, unsigned line, char **path) {
         /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
          * there's no immediate need for action by the user. However, in the interest of making things less confusing
          * to the user, let's still inform the user that these snippets should really be updated. */
-
-        log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s â†’ %s; please update the tmpfiles.d/ drop-in file accordingly.", fname, line, *path, n);
+        log_syntax(NULL, LOG_NOTICE, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s â†’ %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n);
 
         free_and_replace(*path, n);
 
index 271d0bb90ce0638ccaa86da52a10cc85c159d0cd..843c302bf4ba1dba04336084cba99a535650d630 100644 (file)
@@ -238,13 +238,13 @@ finish:
 }
 
 static int send_passwords(const char *socket_name, char **passwords) {
-        _cleanup_free_ char *packet = NULL;
+        _cleanup_(erase_and_freep) char *packet = NULL;
         _cleanup_close_ int socket_fd = -1;
         union sockaddr_union sa = {};
         size_t packet_length = 1;
         char **p, *d;
         ssize_t n;
-        int r, salen;
+        int salen;
 
         assert(socket_name);
 
@@ -266,22 +266,14 @@ static int send_passwords(const char *socket_name, char **passwords) {
                 d = stpcpy(d, *p) + 1;
 
         socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
-        if (socket_fd < 0) {
-                r = log_debug_errno(errno, "socket(): %m");
-                goto finish;
-        }
+        if (socket_fd < 0)
+                return log_debug_errno(errno, "socket(): %m");
 
         n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, salen);
-        if (n < 0) {
-                r = log_debug_errno(errno, "sendto(): %m");
-                goto finish;
-        }
+        if (n < 0)
+                return log_debug_errno(errno, "sendto(): %m");
 
-        r = (int) n;
-
-finish:
-        explicit_bzero_safe(packet, packet_length);
-        return r;
+        return (int) n;
 }
 
 static int parse_password(const char *filename, char **wall) {
index 9698211d1da826ddc00a4b1acc1f17c534b3ee25..a3d7dec88cb0a1fdcd05aab7592acba198374360 100644 (file)
@@ -20,10 +20,11 @@ struct ConfigPerfItem;
 %includes
 %%
 Match.MACAddress,                config_parse_hwaddrs,            0,                             offsetof(link_config, match_mac)
-Match.OriginalName,              config_parse_ifnames,            0,                             offsetof(link_config, match_name)
-Match.Path,                      config_parse_strv,               0,                             offsetof(link_config, match_path)
-Match.Driver,                    config_parse_strv,               0,                             offsetof(link_config, match_driver)
-Match.Type,                      config_parse_strv,               0,                             offsetof(link_config, match_type)
+Match.OriginalName,              config_parse_match_ifnames,      0,                             offsetof(link_config, match_name)
+Match.Path,                      config_parse_match_strv,         0,                             offsetof(link_config, match_path)
+Match.Driver,                    config_parse_match_strv,         0,                             offsetof(link_config, match_driver)
+Match.Type,                      config_parse_match_strv,         0,                             offsetof(link_config, match_type)
+Match.Property,                  config_parse_match_property,     0,                             offsetof(link_config, match_property)
 Match.Host,                      config_parse_net_condition,      CONDITION_HOST,                offsetof(link_config, conditions)
 Match.Virtualization,            config_parse_net_condition,      CONDITION_VIRTUALIZATION,      offsetof(link_config, conditions)
 Match.KernelCommandLine,         config_parse_net_condition,      CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
index 611add9ae0dd210f3e9517e1c5ffea527ef44c94..9989e6ab65bdc623ba0894e5974a0e19f511b84a 100644 (file)
@@ -51,6 +51,7 @@ static void link_config_free(link_config *link) {
         strv_free(link->match_driver);
         strv_free(link->match_type);
         strv_free(link->match_name);
+        strv_free(link->match_property);
         condition_free_list(link->conditions);
 
         free(link->description);
@@ -161,7 +162,7 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
 
         if (set_isempty(link->match_mac) && strv_isempty(link->match_path) &&
             strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
-            strv_isempty(link->match_name) && !link->conditions)
+            strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions)
                 log_warning("%s: No valid settings found in the [Match] section. "
                             "The file will match all interfaces. "
                             "If that is intended, please add OriginalName=* in the [Match] section.",
@@ -240,42 +241,29 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
         assert(ret);
 
         LIST_FOREACH(links, link, ctx->links) {
-                const char *address = NULL, *id_path = NULL, *id_net_driver = NULL, *devtype = NULL, *sysname = NULL;
-
-                (void) sd_device_get_sysattr_value(device, "address", &address);
-                (void) sd_device_get_property_value(device, "ID_PATH", &id_path);
-                (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &id_net_driver);
-                (void) sd_device_get_devtype(device, &devtype);
-                (void) sd_device_get_sysname(device, &sysname);
-
                 if (net_match_config(link->match_mac, link->match_path, link->match_driver,
-                                     link->match_type, link->match_name,
-                                     address ? ether_aton(address) : NULL,
-                                     id_path,
-                                     id_net_driver,
-                                     devtype,
-                                     sysname)) {
+                                     link->match_type, link->match_name, link->match_property,
+                                     device, NULL, NULL)) {
                         if (link->match_name) {
                                 unsigned name_assign_type = NET_NAME_UNKNOWN;
 
                                 (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
 
                                 if (name_assign_type == NET_NAME_ENUM && !strv_contains(link->match_name, "*")) {
-                                        log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
-                                                    link->filename, sysname);
+                                        log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name",
+                                                           link->filename);
                                         *ret = link;
 
                                         return 0;
                                 } else if (name_assign_type == NET_NAME_RENAMED) {
-                                        log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
-                                                    link->filename, sysname);
+                                        log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring",
+                                                           link->filename);
 
                                         continue;
                                 }
                         }
 
-                        log_debug("Config file %s applies to device %s",
-                                  link->filename, sysname);
+                        log_device_debug(device, "Config file %s is applied", link->filename);
 
                         *ret = link;
                         return 0;
index a45a0e709a90b78f1d38099ea00cae87a50ad02d..cd99cd54d4541381963e6c2962d63d5bc0822123 100644 (file)
@@ -40,6 +40,7 @@ struct link_config {
         char **match_driver;
         char **match_type;
         char **match_name;
+        char **match_property;
         LIST_HEAD(Condition, conditions);
 
         char *description;
index 0f29ad7eda727ddcdb3ecaf3a3e9c8d72f030d18..a34e2adbe263b9119f987e30c980d9429a1f4ef7 100755 (executable)
@@ -29,7 +29,7 @@ Type=oneshot
 EOF
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index aed1c591069b203f242ba7085b731173a03b99f0..9d25e942500fb3336d7963e1c9bca9dd87f2dc07 100755 (executable)
@@ -75,7 +75,7 @@ EOF
         cat >>$initdir/etc/fstab <<EOF
 /dev/mapper/varcrypt    /var    ext4    defaults 0 1
 EOF
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root/var"
     umount $TESTDIR/root/var
index 89125109d894554b0c17caca30ac686a6d00f0e1..2a7df79a47868329e427303fdeb8fa9e12d70a80 100755 (executable)
@@ -44,7 +44,7 @@ EOF
         cp test-jobs.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index f24a8f6be7a3dc94d8f5165100458a8e20768c7d..a5ba7c84349813cb0aa6889e06847ffa79d01816 100755 (executable)
@@ -46,7 +46,7 @@ EOF
         cp test-journal.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 3c29b2ee3fe0f6e17b3cdb46d566740c1f2f90e6..176014d270af1a7ebf789d077f126cbf23a4b639 100755 (executable)
@@ -42,7 +42,7 @@ EOF
         cp test-rlimits.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 2b49b3d5ae3551cba2c0871df54486da2341003a..5d26cb0f0a4bca756232db4d1b94590f087e5d30 100755 (executable)
@@ -92,7 +92,7 @@ EOF
         dracut_install -o sesearch
         dracut_install runcon
         dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile
-    ) || return 1
+    )
 
     # mask some services that we do not want to run in these tests
     ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
index 93ddb6f5fbb28d2b5af371999f6ae8632e36110e..e488cb4347f9bc81b28f0bd95898f8f62ecb13a6 100755 (executable)
@@ -40,7 +40,7 @@ EOF
         cp test-segfault.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index ef2aba0e17e501c1a4f91b0d09c9f6d86e4c74b5..d455d5d555ca134c59a49f195692f886bf8a6b5b 100755 (executable)
@@ -60,7 +60,7 @@ ExecStart=/bin/systemctl reload /
 EOF
 
         setup_testsuite
-    ) || return 1
+    )
 
     ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/root.mount
     mkdir -p $initdir/etc/systemd/system/local-fs.target.wants
index 8e7402fcd46c20238ea785f43429180157f2bba6..bef31cd096e2faca96c585dc1dd16dda58425a2f 100755 (executable)
@@ -32,7 +32,7 @@ TimeoutStopSec=270s
 EOF
 
         setup_testsuite
-    ) || return 1
+    )
 
     # mask some services that we do not want to run in these tests
     ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
index dc7a9acaa102078589ddce1ac0e15abecd141c3a..081d22b44d23e561eb5a5b4ac946141f9a30c7d0 100755 (executable)
@@ -45,7 +45,7 @@ ExecStart=/bin/true
 EOF
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     # mask some services that we do not want to run in these tests
index 3419b78fe797e2469856fefdcbf6467828847372..267224c0429ec33eb06eb8ee95c2d67275bc271b 100755 (executable)
@@ -64,7 +64,7 @@ EOF
 
         chmod 0755 $initdir/test-fail-on-restart.sh
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 31cf1b471ae20d2a57b04e35b022b99e15568907..08b59ae165ca5e29953d0a724d6d8ca6c66a43ed 100755 (executable)
@@ -90,7 +90,7 @@ EOF
 
         chmod 0755 $initdir/test-socket-group.sh
         setup_testsuite
-    ) || return 1
+    )
 
     setup_nspawn_root
 
index 8252c4b2aaf47b6f34ce3b71c4c76227ab2eebaf..6a40bebbe0ce8cbc014a8392a4b02e55f24f92aa 100755 (executable)
@@ -184,7 +184,7 @@ EOF
 
         chmod 0755 $initdir/test-nspawn.sh
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 33e311a1e7ea17ac491286c20e25f11abc5717d9..c22fc7c3c060acd019e98c9a7d0bdf0542cf68a6 100755 (executable)
@@ -73,7 +73,7 @@ EOF
 chmod +x $initdir/test-machine-id-setup.sh
 
         setup_testsuite
-    ) || return 1
+    )
 
     # mask some services that we do not want to run in these tests
     ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
index 6613e32fc9072b349a26feaeca5cf5d13a7b563d..7e6dc45f6bc7221fac9630643f5ee5b172f61638 100755 (executable)
@@ -30,7 +30,7 @@ test_setup() {
         cp $BUILD_DIR/src/shared/libsystemd-shared-*.so ${initdir}/usr/lib
 
         setup_testsuite
-    ) || return 1
+    )
     # mask some services that we do not want to run in these tests
     ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
     ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
index 9bd6e98644adab7a634509425f211b32bf2f75b0..02578d33c79e305d2dc6906ecabf18153a7832a7 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 277cc2c798968f7462feba3237c1c576e696281b..0cf6391bdcd6d1fc1199c1ff77914cba8e885474 100755 (executable)
@@ -30,7 +30,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     # mask some services that we do not want to run in these tests
index 3ed6a1b928a0eb589bfca80cd355dd77a1dd960b..25461af9dc4f018a132f94c2acc88e4e2682b32e 100755 (executable)
@@ -40,7 +40,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index bf80e8b5844f95ca447c0d97de30e3d552f67c62..8adaf490e2ec475534841d982d257684d6affb28 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 6ed22be366431de0769fcf857a0dd390f53ac8d4..68423637cea130b563e2615138e0787cd14e043c 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 038303edf8fe993bf46cf584ec40b03fa87435c7..5d60b548dd50b9847196f2dba4d97d8d77a10196 100755 (executable)
@@ -91,7 +91,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     # mask some services that we do not want to run in these tests
index 7fe367c3be6d3f7e962f29ed0a597baa676d2b03..4beaa6456e762e571b2b8ff9f164e847b0756667 100755 (executable)
@@ -31,7 +31,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 9a2913d330c0ba32194fb7c53f5407f20a8832d3..b1a965aff1147347c598d19665296a1f28807baa 100755 (executable)
@@ -30,7 +30,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index fb35f80ec1a592c540c02e69acb4ac59c9f5e2b5..e78e317d6d41508e64835724c13037e2ef23c2f2 100755 (executable)
@@ -40,7 +40,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 67be1d51ccc474c6e396ed9051fd832221971f6a..42db3b621dd4b3de89fff3de710aedf7bfdd9095 100755 (executable)
@@ -49,7 +49,7 @@ ExecStart=/bin/true
 EOF
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
         # mask some services that we do not want to run in these tests
index 26ad2f902d1e4a094c9279c3bdead2f78ed6126f..3e297492eaefbbb05e5b4c8d932aa999a29543e2 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 40e6ff25cd5b9dc6cd9020b22bec47cfa45788bd..47f1fff1d3d1cec6f6f071ffe4a1a8bc86a50868 100755 (executable)
@@ -49,7 +49,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 7156528873dba5b187ba1846c0c4bf8d23e1dbef..1eda377ea0f017f9cf7ed68688e5563c58b9d5cc 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 7e9431dd11df8951a168957c427340ca5c906f12..aef3db5db52def9a2247f977bc8fecc63b1c9928 100755 (executable)
@@ -41,7 +41,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
 
     ddebug "umount $TESTDIR/root"
     umount $TESTDIR/root
index 8ef28b05f7fb4167419b5d491b1a3f221b1da53b..5964311793ccc9fe303736ca5dfb61a8a7844610 100755 (executable)
@@ -38,7 +38,7 @@ EOF
         cp testsuite.sh $initdir/
 
         setup_testsuite
-    ) || return 1
+    )
     setup_nspawn_root
 
     ddebug "umount $TESTDIR/root"
index 5925e5ad12d046f7eecdfde0ef16297ccae384b9..61155063a8bfe137e28b545c9e58b8074cbfe8cd 100644 (file)
@@ -4,6 +4,7 @@ OriginalName=
 Path=
 Driver=
 Type=
+Property=
 Host=
 Virtualization=
 KernelCommandLine=
diff --git a/test/fuzz/fuzz-netdev-parser/27-xfrm.netdev b/test/fuzz/fuzz-netdev-parser/27-xfrm.netdev
new file mode 100644 (file)
index 0000000..cdcb2d2
--- /dev/null
@@ -0,0 +1,7 @@
+[NetDev]
+Name=xfrm99
+Kind=xfrm
+
+[Xfrm]
+InterfaceId=7
+Independent=false
index be1b197024b5d46b70dfb7fd19c0e6858077c32a..07e54d9e44f5d0c201c47407ccc981aad4a4d7af 100644 (file)
@@ -207,3 +207,6 @@ KeyId=
 Key=
 KeyFile=
 Activate=
+[Xfrm]
+Independent=
+InterfaceId=
diff --git a/test/fuzz/fuzz-network-parser/27-xfrm.network b/test/fuzz/fuzz-network-parser/27-xfrm.network
new file mode 100644 (file)
index 0000000..fa26c84
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm99
index 496c52336cb6d312241c306e52c48536ba4ba806..ddafaa7840cc528b417017276b80f4cb596d66a0 100644 (file)
@@ -20,6 +20,7 @@ Driver=
 Architecture=
 Path=
 Name=
+Property=
 Virtualization=
 KernelCommandLine=
 Host=
@@ -120,6 +121,7 @@ DNSSEC=
 IPv6HopLimit=
 IPForward=
 IPv6Token=
+Xfrm=
 Description=
 VXLAN=
 L2TP=
diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-15678 b/test/fuzz/fuzz-network-parser/oss-fuzz-15678
new file mode 100644 (file)
index 0000000..2a37d5f
--- /dev/null
@@ -0,0 +1,2 @@
+[IPv6AcceptRA]
+BlackList=70:: 70::
\ No newline at end of file
index 4a76dd70ea10cb97190bc9dbd36884d172cd86fb..5dbbff0f068a2c87f4220ca2671684e8b75a63df 100644 (file)
@@ -395,8 +395,8 @@ create_asan_wrapper() {
 
 set -x
 
-DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
-DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+DEFAULT_ASAN_OPTIONS=${ASAN_OPTIONS:-strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1}
+DEFAULT_UBSAN_OPTIONS=${UBSAN_OPTIONS:-print_stacktrace=1:print_summary=1:halt_on_error=1}
 DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS"
 
 # As right now bash is the PID 1, we can't expect PATH to have a sane value.
@@ -659,6 +659,7 @@ install_execs() {
          # some {rc,halt}.local scripts and programs are okay to not exist, the rest should
          # also, plymouth is pulled in by rescue.service, but even there the exit code
          # is ignored; as it's not present on some distros, don't fail if it doesn't exist
+         dinfo "Attempting to install $i"
          inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "/bin/plymouth" == "$i" ]
      done
     )
@@ -1238,6 +1239,14 @@ find_binary() {
 # Install binary executable, and all shared library dependencies, if any.
 inst_binary() {
     local _bin _target
+
+    # In certain cases we might attempt to install a binary which is already
+    # present in the test image, yet it's missing from the host system.
+    # In such cases, let's check if the binary indeed exists in the image
+    # before doing any other chcecks. If it does, immediately return with
+    # success.
+    [[ $# -eq 1 && -e $initdir/$1 ]] && return 0
+
     _bin=$(find_binary "$1") || return 1
     _target=${2:-$_bin}
     [[ -e $initdir/$_target ]] && return 0
diff --git a/test/test-network/conf/13-not-match-udev-property.network b/test/test-network/conf/13-not-match-udev-property.network
new file mode 100644 (file)
index 0000000..f0a530e
--- /dev/null
@@ -0,0 +1,6 @@
+[Match]
+Name=dummy98
+Property=INTERFACE=hoge
+
+[Network]
+IPv6AcceptRA=false
diff --git a/test/test-network/conf/14-match-udev-property.network b/test/test-network/conf/14-match-udev-property.network
new file mode 100644 (file)
index 0000000..b632af1
--- /dev/null
@@ -0,0 +1,7 @@
+[Match]
+Name=dummy98
+Property=INTERFACE=dummy98
+
+[Network]
+IPv6AcceptRA=false
+Address=10.1.2.3/16
diff --git a/test/test-network/conf/26-bridge-vlan-master.network b/test/test-network/conf/26-bridge-vlan-master.network
new file mode 100644 (file)
index 0000000..8493e32
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=bridge99
+
+[Network]
+IPv6AcceptRA=false
+
+[BridgeVLAN]
+VLAN=4060-4094
diff --git a/test/test-network/conf/26-bridge-vlan-slave.network b/test/test-network/conf/26-bridge-vlan-slave.network
new file mode 100644 (file)
index 0000000..ba50508
--- /dev/null
@@ -0,0 +1,9 @@
+[Match]
+Name=test1
+
+[Network]
+IPv6AcceptRA=no
+Bridge=bridge99
+
+[BridgeVLAN]
+VLAN=4064-4094
diff --git a/test/test-network/conf/dhcp-client-use-routes-no.network b/test/test-network/conf/dhcp-client-use-routes-no.network
new file mode 100644 (file)
index 0000000..0c97ef5
--- /dev/null
@@ -0,0 +1,18 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+
+[Route]
+Destination=192.168.5.0/24
+
+[Route]
+Destination=192.168.6.0/24
+
+[Route]
+Destination=192.168.7.0/24
+
+[DHCP]
+UseRoutes=no
diff --git a/test/test-network/conf/dhcp-client-with-static-address.network b/test/test-network/conf/dhcp-client-with-static-address.network
new file mode 100644 (file)
index 0000000..b4e11be
--- /dev/null
@@ -0,0 +1,7 @@
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+Address=192.168.5.250
index 9c274c128deb3124704ed3316f65068df4f69591..92f1a5bd8dbeef5d34f407d253722c8e3307306f 100755 (executable)
@@ -26,7 +26,7 @@ networkd_bin='/usr/lib/systemd/systemd-networkd'
 wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
 networkctl_bin='/usr/bin/networkctl'
 use_valgrind=False
-enable_debug=False
+enable_debug=True
 env = {}
 asan_options=None
 lsan_options=None
@@ -91,6 +91,23 @@ def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
 
     return f
 
+def expectedFailureIfLinkFileFieldIsNotSet():
+    def f(func):
+        support = False
+        rc = call('ip link add name dummy99 type dummy')
+        if rc == 0:
+            ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+            if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
+                support = True
+            call('ip link del dummy99')
+
+        if support:
+            return func
+        else:
+            return unittest.expectedFailure(func)
+
+    return f
+
 def expectedFailureIfEthtoolDoesNotSupportDriver():
     def f(func):
         support = False
@@ -265,17 +282,28 @@ def remove_log_file():
     if os.path.exists(dnsmasq_log_file):
         os.remove(dnsmasq_log_file)
 
-def start_networkd(sleep_sec=0, remove_state_files=True):
-    if (remove_state_files and
-        os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
-        check_output('systemctl stop systemd-networkd')
+def remove_networkd_state_files():
+    if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
         os.remove(os.path.join(networkd_runtime_directory, 'state'))
-        check_output('systemctl start systemd-networkd')
-    else:
-        check_output('systemctl restart systemd-networkd')
+
+def stop_networkd(show_logs=True, remove_state_files=True):
+    if show_logs:
+        invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
+    check_output('systemctl stop systemd-networkd')
+    if show_logs:
+        print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
+    if remove_state_files:
+        remove_networkd_state_files()
+
+def start_networkd(sleep_sec=0):
+    check_output('systemctl start systemd-networkd')
     if sleep_sec > 0:
         time.sleep(sleep_sec)
 
+def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
+    stop_networkd(show_logs, remove_state_files)
+    start_networkd(sleep_sec)
+
 def wait_online(links_with_operstate, timeout='20s', bool_any=False):
     args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
     if bool_any:
@@ -331,10 +359,12 @@ class NetworkctlTests(unittest.TestCase, Utilities):
 
     def setUp(self):
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_glob(self):
         copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
@@ -371,6 +401,35 @@ class NetworkctlTests(unittest.TestCase, Utilities):
         output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
         self.assertRegex(output, 'MTU: 1600')
 
+    def test_type(self):
+        copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+        start_networkd()
+        wait_online(['test1:degraded'])
+
+        output = check_output(*networkctl_cmd, 'status', 'test1')
+        print(output)
+        self.assertRegex(output, 'Type: ether')
+
+        output = check_output(*networkctl_cmd, 'status', 'lo')
+        print(output)
+        self.assertRegex(output, 'Type: loopback')
+
+    @expectedFailureIfLinkFileFieldIsNotSet()
+    def test_udev_link_file(self):
+        copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+        start_networkd()
+        wait_online(['test1:degraded'])
+
+        output = check_output(*networkctl_cmd, 'status', 'test1')
+        print(output)
+        self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link')
+        self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
+
+        output = check_output(*networkctl_cmd, 'status', 'lo')
+        print(output)
+        self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link')
+        self.assertRegex(output, r'Network File: n/a')
+
     @expectedFailureIfEthtoolDoesNotSupportDriver()
     def test_udev_driver(self):
         copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
@@ -463,6 +522,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '11-dummy.netdev',
         '11-dummy.network',
         '12-dummy.netdev',
+        '13-not-match-udev-property.network',
+        '14-match-udev-property.network',
         '15-name-conflict-test.netdev',
         '21-macvlan.netdev',
         '21-macvtap.netdev',
@@ -562,11 +623,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
     def setUp(self):
         remove_fou_ports(self.fou_ports)
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_fou_ports(self.fou_ports)
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_dropin_and_name_conflict(self):
         copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
@@ -578,6 +641,15 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, '00:50:56:c0:00:28')
 
+    def test_match_udev_property(self):
+        copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
+        start_networkd()
+        wait_online(['dummy98:routable'])
+
+        output = check_output('networkctl status dummy98')
+        print(output)
+        self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
+
     def test_wait_online_any(self):
         copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
         start_networkd()
@@ -1169,11 +1241,13 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
     def setUp(self):
         remove_l2tp_tunnels(self.l2tp_tunnel_ids)
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_l2tp_tunnels(self.l2tp_tunnel_ids)
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
     def test_l2tp_udp(self):
@@ -1267,12 +1341,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
         remove_routes(self.routes)
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
         remove_routes(self.routes)
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_address_static(self):
         copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
@@ -1354,7 +1430,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
 
         for trial in range(3):
             # Remove state files only first time
-            start_networkd(0, remove_state_files=(trial == 0))
+            start_networkd()
             wait_online(['test1:degraded', 'dummy98:degraded'])
             time.sleep(1)
 
@@ -1366,6 +1442,8 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
             print(output)
             self.assertRegex(output, '112:     from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
 
+            stop_networkd(remove_state_files=False)
+
     @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
     def test_routing_policy_rule_port_range(self):
         copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
@@ -1572,7 +1650,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
         check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
 
-        start_networkd()
+        restart_networkd()
         wait_online(['dummy98:routable'])
 
         output = check_output('ip -4 address show dummy98')
@@ -1691,10 +1769,12 @@ class NetworkdBondTests(unittest.TestCase, Utilities):
 
     def setUp(self):
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_bond_active_slave(self):
         copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
@@ -1781,6 +1861,8 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
         '26-bridge.netdev',
         '26-bridge-slave-interface-1.network',
         '26-bridge-slave-interface-2.network',
+        '26-bridge-vlan-master.network',
+        '26-bridge-vlan-slave.network',
         'bridge99-ignore-carrier-loss.network',
         'bridge99.network']
 
@@ -1789,11 +1871,33 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
     def setUp(self):
         remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
+
+    def test_bridge_vlan(self):
+        copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
+                                        '26-bridge.netdev', '26-bridge-vlan-master.network')
+        start_networkd()
+        wait_online(['test1:enslaved', 'bridge99:degraded'])
+
+        output = check_output('bridge vlan show dev test1')
+        print(output)
+        self.assertNotRegex(output, '4063')
+        for i in range(4064, 4095):
+            self.assertRegex(output, f'{i}')
+        self.assertNotRegex(output, '4095')
+
+        output = check_output('bridge vlan show dev bridge99')
+        print(output)
+        self.assertNotRegex(output, '4059')
+        for i in range(4060, 4095):
+            self.assertRegex(output, f'{i}')
+        self.assertNotRegex(output, '4095')
 
     def test_bridge_property(self):
         copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
@@ -1906,10 +2010,12 @@ class NetworkdLLDPTests(unittest.TestCase, Utilities):
 
     def setUp(self):
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_lldp(self):
         copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
@@ -1931,10 +2037,12 @@ class NetworkdRATests(unittest.TestCase, Utilities):
 
     def setUp(self):
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_ipv6_prefix_delegation(self):
         warn_about_firewalld()
@@ -1958,10 +2066,12 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
 
     def setUp(self):
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_dhcp_server(self):
         warn_about_firewalld()
@@ -2009,9 +2119,11 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         'dhcp-client-listen-port.network',
         'dhcp-client-route-metric.network',
         'dhcp-client-route-table.network',
+        'dhcp-client-use-routes-no.network',
         'dhcp-client-vrf.network',
         'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
         'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
+        'dhcp-client-with-static-address.network',
         'dhcp-client.network',
         'dhcp-server-veth-peer.network',
         'dhcp-v4-server-veth-peer.network',
@@ -2020,6 +2132,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
     def setUp(self):
         stop_dnsmasq(dnsmasq_pid_file)
         remove_links(self.links)
+        stop_networkd(show_logs=False)
 
     def tearDown(self):
         stop_dnsmasq(dnsmasq_pid_file)
@@ -2027,6 +2140,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         remove_log_file()
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        stop_networkd(show_logs=True)
 
     def test_dhcp_client_ipv6_only(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
@@ -2160,6 +2274,26 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, '192.168.5.* dynamic')
 
+    def test_dhcp_client_with_static_address(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
+                                        'dhcp-client-with-static-address.network')
+        start_networkd()
+        wait_online(['veth-peer:carrier'])
+        start_dnsmasq()
+        wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        output = check_output('ip address show dev veth99 scope global')
+        print(output)
+        self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
+        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
+
+        output = check_output('ip route show dev veth99')
+        print(output)
+        self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+        self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
+        self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
+        self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+
     def test_dhcp_route_table_id(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
         start_networkd()
@@ -2183,6 +2317,38 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, 'metric 24')
 
+    def test_dhcp_client_use_routes_no(self):
+        copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+                                        'dhcp-client-use-routes-no.network')
+        start_networkd()
+        wait_online(['veth-peer:carrier'])
+        start_dnsmasq(lease_time='2m')
+        wait_online(['veth99:routable', 'veth-peer:routable'])
+
+        output = check_output('ip address show dev veth99 scope global')
+        print(output)
+        self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+
+        output = check_output('ip route show dev veth99')
+        print(output)
+        self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
+        self.assertRegex(output, r'192.168.5.0/24 proto static')
+        self.assertRegex(output, r'192.168.6.0/24 proto static')
+        self.assertRegex(output, r'192.168.7.0/24 proto static')
+
+        # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
+        print('Wait for the dynamic address to be renewed')
+        time.sleep(125)
+
+        wait_online(['veth99:routable'])
+
+        output = check_output('ip route show dev veth99')
+        print(output)
+        self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
+        self.assertRegex(output, r'192.168.5.0/24 proto static')
+        self.assertRegex(output, r'192.168.6.0/24 proto static')
+        self.assertRegex(output, r'192.168.7.0/24 proto static')
+
     def test_dhcp_keep_configuration_dhcp(self):
         copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
         start_networkd()
@@ -2255,7 +2421,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, r'192.168.5.*')
 
-        start_networkd()
+        restart_networkd()
         wait_online(['veth-peer:routable'])
 
         output = check_output('ip address show dev veth99 scope global')
@@ -2290,7 +2456,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
 
         # When networkd started, the links are already configured, so let's wait for 5 seconds
         # the links to be re-configured.
-        start_networkd(5)
+        restart_networkd(5)
         wait_online(['veth99:routable', 'veth-peer:routable'])
 
         output = check_output('ip -4 address show dev veth99 scope global')
index b37b2e975f5e22a7b9ffe88e1a465f4177cdae9f..85ec41b64135d3c5e09365aa3e567b056403b590 100755 (executable)
@@ -1713,6 +1713,12 @@ sub run_test {
 
 }
 
+sub cleanup {
+        system("rm", "-rf", "$udev_run");
+        system("umount", "$udev_tmpfs");
+        rmdir($udev_tmpfs);
+}
+
 # only run if we have root permissions
 # due to mknod restrictions
 if (!($<==0)) {
@@ -1729,11 +1735,13 @@ if ($? >> 8 == 0) {
 
 if (!udev_setup()) {
         warn "Failed to set up the environment, skipping the test";
+        cleanup();
         exit($EXIT_TEST_SKIP);
 }
 
 if (system($udev_bin, "check")) {
         warn "$udev_bin failed to set up the environment, skipping the test";
+        cleanup();
         exit($EXIT_TEST_SKIP);
 }
 
@@ -1776,10 +1784,7 @@ if ($list[0]) {
 
 print "$error errors occurred\n\n";
 
-# cleanup
-system("rm", "-rf", "$udev_run");
-system("umount", "$udev_tmpfs");
-rmdir($udev_tmpfs);
+cleanup();
 
 if ($error > 0) {
         exit(1);
index 0080b065d89cf201f06a2546ca782d1c393f67bd..3fe7e1a8031b48468d7c8fea9cb6c534f0c6ef5d 100755 (executable)
@@ -9,7 +9,7 @@ REPO_ROOT=${REPO_ROOT:-$(pwd)}
 sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
 sudo apt-get update -y
 sudo apt-get build-dep systemd -y
-sudo apt-get install -y ninja-build python3-pip python3-setuptools
+sudo apt-get install -y ninja-build python3-pip python3-setuptools quota
 pip3 install meson
 
 cd $REPO_ROOT
index 475a1510aa20ef3bc0faa3769e54706bd78f7316..076e8f9325909f5c6652a467fe43377e60885eea 100755 (executable)
@@ -32,6 +32,7 @@ PACKAGES=(cryptsetup-bin
           python3-pyparsing
           python3-setuptools
           qemu-system-x86
+          quota
           strace
           unifont
           util-linux)
index a8eab94d02e524738f58210bf200afee034e6033..c88d3597b7a47ac3f40cbc12edad4d21e15914ac 100644 (file)
@@ -22,6 +22,7 @@ ProtectHostname=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallFilter=@system-service @mount
+SystemCallErrorNumber=EPERM
 SystemCallArchitectures=native
 LockPersonality=yes
 IPAddressDeny=any