]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #10897 from keszybz/etc-fstab-parsing
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Dec 2018 11:31:30 +0000 (12:31 +0100)
committerGitHub <noreply@github.com>
Mon, 10 Dec 2018 11:31:30 +0000 (12:31 +0100)
Forbid dashes in hostnames and /etc/fstab parsing improvements

192 files changed:
.dir-locals.el
.lgtm.yml
.travis.yml
.vimrc
README.md
TODO
docs/CODING_STYLE.md
hwdb/60-sensor.hwdb
hwdb/ids_parser.py
hwdb/parse_hwdb.py
man/.dir-locals.el
man/systemd-journald.service.xml
man/systemd.mount.xml
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.swap.xml
man/systemd.unit.xml
shell-completion/bash/systemd-analyze
src/activate/activate.c
src/basic/arphrd-list.c
src/basic/fd-util.c
src/basic/generate-af-list.sh
src/basic/generate-arphrd-list.sh
src/basic/macro.h
src/basic/meson.build
src/basic/missing.h
src/basic/missing_audit.h [new file with mode: 0644]
src/basic/missing_drm.h [new file with mode: 0644]
src/basic/missing_fcntl.h [new file with mode: 0644]
src/basic/missing_fs.h [new file with mode: 0644]
src/basic/missing_input.h
src/basic/missing_mman.h [new file with mode: 0644]
src/basic/missing_network.h
src/basic/missing_random.h [new file with mode: 0644]
src/basic/missing_resource.h [new file with mode: 0644]
src/basic/missing_sched.h [new file with mode: 0644]
src/basic/missing_socket.h [new file with mode: 0644]
src/basic/missing_stat.h
src/basic/missing_stdlib.h [new file with mode: 0644]
src/basic/missing_syscall.h
src/basic/missing_timerfd.h [new file with mode: 0644]
src/basic/mountpoint-util.c
src/basic/parse-util.c
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/rlimit-util.c [moved from src/shared/rlimit-util.c with 94% similarity]
src/basic/rlimit-util.h [moved from src/shared/rlimit-util.h with 96% similarity]
src/basic/socket-util.h
src/basic/terminal-util.h
src/basic/time-util.c
src/core/automount.c
src/core/bpf-firewall.c
src/core/dbus-job.c
src/core/dbus-job.h
src/core/dbus-unit.c
src/core/dbus-unit.h
src/core/device.c
src/core/execute.h
src/core/job.c
src/core/main.c
src/core/mount.c
src/core/mount.h
src/core/path.c
src/core/scope.c
src/core/service.c
src/core/shutdown.c
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/target.c
src/core/timer.c
src/core/unit.c
src/coredump/coredumpctl.c
src/delta/delta.c
src/fsck/fsck.c
src/fuzz/fuzz-ndisc-rs.c
src/import/pull-common.c
src/journal-remote/journal-gatewayd.c
src/journal-remote/journal-remote-main.c
src/journal-remote/journal-remote.c
src/journal-remote/journal-remote.h
src/journal-remote/journal-upload.c
src/journal-remote/microhttpd-util.h
src/journal/audit-type.c
src/journal/audit-type.h
src/journal/meson.build
src/libsystemd-network/sd-lldp.c
src/libsystemd-network/test-dhcp6-client.c
src/libsystemd/meson.build
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-dump.c
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/test-bus-benchmark.c
src/libsystemd/sd-device/sd-device.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/rtnl-message.c
src/libsystemd/sd-resolve/test-resolve.c
src/login/inhibit.c
src/machine/image-dbus.c
src/machine/machine-dbus.c
src/machine/machined-dbus.c
src/network/meson.build
src/network/netdev/fou-tunnel.h
src/network/netdev/ipvlan.h
src/network/netdev/netdev-gperf.gperf
src/network/netdev/tunnel.c
src/network/netdev/tunnel.h
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-lldp-tx.c
src/network/networkd-neighbor.c [new file with mode: 0644]
src/network/networkd-neighbor.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-routing-policy-rule.c
src/network/networkd-routing-policy-rule.h
src/network/networkd.c
src/network/wait-online/wait-online.c
src/nspawn/nspawn-network.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn-setuid.c
src/nspawn/nspawn.c
src/partition/makefs.c
src/portable/portabled-bus.c
src/portable/portabled-image-bus.c
src/quotacheck/quotacheck.c
src/rc-local-generator/rc-local-generator.c
src/remount-fs/remount-fs.c
src/resolve/resolvconf-compat.c
src/resolve/resolvectl.c
src/resolve/resolvectl.h
src/resolve/resolved-bus.c
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-dns-stream.c
src/resolve/resolved-dns-stream.h
src/resolve/resolved-dns-stub.c
src/resolve/resolved-dns-synthesize.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dnssd-bus.c
src/resolve/resolved-llmnr.c
src/resolve/resolved-manager.c
src/resolve/resolved.c
src/resolve/test-resolved-etc-hosts.c
src/shared/blkid-util.h
src/shared/bus-unit-util.c
src/shared/conf-parser.c
src/shared/daemon-util.h [new file with mode: 0644]
src/shared/exec-util.c
src/shared/generator.c
src/shared/lockfile-util.h
src/shared/logs-show.c
src/shared/machine-image.c
src/shared/meson.build
src/shared/nsflags.c
src/shared/nsflags.h
src/shared/pager.c
src/sulogin-shell/sulogin-shell.c
src/systemctl/systemctl.c
src/systemd/sd-netlink.h
src/test/test-arphrd-list.c
src/test/test-socket-util.c
src/test/test-systemd-tmpfiles.py
src/timesync/timesyncd.c
src/udev/net/ethtool-util.h
src/udev/udev-ctrl.c
src/udev/udev-event.c
src/udev/udevd.c
src/vconsole/vconsole-setup.c
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/25-neighbor-section.network [new file with mode: 0644]
test/fuzz/fuzz-network-parser/26-bridge-slave-interface-1.network
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-unit-file/directives.service
test/test-network/conf/25-fibrule-invert.network [new file with mode: 0644]
test/test-network/conf/25-isatap-tunnel.netdev [new file with mode: 0644]
test/test-network/conf/25-neighbor-section.network [new file with mode: 0644]
test/test-network/conf/26-bridge-slave-interface-1.network
test/test-network/conf/isatap.network [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py
tools/catalog-report.py
tools/gdb-sd_dump_hashmaps.py
tools/generate-gperfs.py
tools/make-directive-index.py
tools/make-man-index.py
tools/make-man-rules.py
tools/xml_helper.py
travis-ci/managers/debian.sh [new file with mode: 0755]

index e3d01b28a9790e22943f1f148efe701adc60459b..676d7552312a748ff25f3758d98b265e0fc1cba0 100644 (file)
@@ -2,14 +2,14 @@
 ; A list of (major-mode . ((var1 . value1) (var2 . value2)))
 ; Mode can be nil, which gives default values.
 
-; Note that we set a line width of 119 for .c and XML files, but for everything
+; Note that we set a line width of 109 for .c and XML files, but for everything
 ; else (such as journal catalog files, unit files, README files) we stick to a
 ; more conservative 79 characters.
 
 ; NOTE: If you update this file make sure to update .vimrc and .editorconfig,
 ; too.
 
-((c-mode . ((fill-column . 119)
+((c-mode . ((fill-column . 109)
             (c-basic-offset . 8)
             (eval . (c-set-offset 'substatement-open 0))
             (eval . (c-set-offset 'statement-case-open 0))
@@ -17,7 +17,7 @@
             (eval . (c-set-offset 'arglist-intro '++))
             (eval . (c-set-offset 'arglist-close 0))))
  (nxml-mode . ((nxml-child-indent . 2)
-               (fill-column . 119)))
+               (fill-column . 109)))
  (meson-mode . ((meson-indent-basic . 8)))
  (sh-mode . ((sh-basic-offset . 8)
              (sh-indentation . 8)))
index 37f9c4335c2e127b98b2e98c1a08db2f3e622cb4..5948d8c2bc0d7fc7f941cd62c843f4bd6b7ed887 100644 (file)
--- a/.lgtm.yml
+++ b/.lgtm.yml
@@ -8,3 +8,6 @@ extraction:
     after_prepare:
       - pip3 install meson
       - export PATH="$HOME/.local/bin/:$PATH"
+  python:
+    python_setup:
+      version: 3
index f2128ea1a7a1346dc3f8765236d3ca03025f485c..f50731fe3fa56e900aba6cec40b3740318a66e4a 100644 (file)
@@ -90,6 +90,24 @@ jobs:
           after_script:
               - $CI_MANAGERS/fedora.sh CLEANUP
 
+        - name: Debian Testing
+          language: bash
+          env:
+              - DEBIAN_RELEASE="testing"
+              - CONT_NAME="systemd-debian-$DEBIAN_RELEASE"
+              - DOCKER_EXEC="docker exec -ti $CONT_NAME"
+          before_install:
+              - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
+              - docker --version
+          install:
+              - $CI_MANAGERS/debian.sh SETUP
+          script:
+              - set -e
+              - $CI_MANAGERS/debian.sh RUN
+              - set +e
+          after_script:
+              - $CI_MANAGERS/debian.sh CLEANUP
+
         - stage: Coverity
           language: bash
           env:
diff --git a/.vimrc b/.vimrc
index 284bf88494c574f0aefb4f76650b5a1320af4489..a62546d8e2aa8a834ba2f3ecdab2069b8c5958cb 100644 (file)
--- a/.vimrc
+++ b/.vimrc
@@ -4,7 +4,7 @@
 " You should consider setting 'set secure' as well, which is highly
 " recommended!
 
-" Note that we set a line width of 119 for .c and XML files, but for everything
+" Note that we set a line width of 109 for .c and XML files, but for everything
 " else (such as journal catalog files, unit files, README files) we stick to a
 " more conservative 79 characters.
 
@@ -16,5 +16,5 @@ set shiftwidth=8
 set expandtab
 set makeprg=GCC_COLORS=\ make
 set tw=79
-au BufRead,BufNewFile *.xml set tw=119 shiftwidth=2 smarttab
-au FileType c set tw=119
+au BufRead,BufNewFile *.xml set tw=109 shiftwidth=2 smarttab
+au FileType c set tw=109
index 7d6e0d99a802116403ad7fa1a1d0b77a7655dd39..72484f620c1acfeff010b18ed80bab2f9e5dce0e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,11 +2,12 @@
 
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
-[![Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
+[![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
 [![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
-[![Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
-[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)
+[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
+[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
+[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)
 
 ## Details
 
diff --git a/TODO b/TODO
index cafd75a01daa5c3952b7ad0b183062d9be530c4c..3a4eac4b2c0b15abdb54841562cb7f5b8dbd9f4a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -23,8 +23,16 @@ Janitorial Clean-ups:
 
 Features:
 
+* when importing an fs tree with machined, optionally apply userns-rec-chown
+
+* when importing an fs tree with machined, complain if image is not an OS
+
 * when we fork off generators and such, lower LIMIT_NOFILE soft limit to 1K
 
+* Maybe introduce a helper safe_exec() or so, which is to execve() which
+  safe_fork() is to fork(). And then make revert the RLIMIT_NOFILE soft limit
+  to 1K implicitly, unless explicitly opted-out.
+
 * rework seccomp/nnp logic that that even if User= is used in combination with
   a seccomp option we don't have to set NNP. For that, change uid first whil
   keeping CAP_SYS_ADMIN, then apply seccomp, the drop cap.
index bbc528b1404d2ccd737d3c4e52201742401b25c9..a91e119c4a9a5e8e2c149ea3275440c8a812f5f1 100644 (file)
@@ -11,7 +11,7 @@
 
 - Don't break code lines too eagerly. We do **not** force line breaks at 80ch,
   all of today's screens should be much larger than that. But then again, don't
-  overdo it, ~119ch should be enough really. The `.editorconfig`, `.vimrc` and
+  overdo it, ~109ch should be enough really. The `.editorconfig`, `.vimrc` and
   `.dir-locals.el` files contained in the repository will set this limit up for
   you automatically, if you let them (as well as a few other things).
 
index 9925175e2914fc1d932fc624cffab8038f2c8ec1..c0306bd3ab81d969c8d9441b123b01db8ef65fb4 100644 (file)
@@ -401,6 +401,16 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1013:bd08/22
 sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+# Point of View TAB-P1005W-232 (v2.0)
+sensor:modalias:acpi:KIOX000A*:dmi:*:rvnPOV:rnI102A:*
+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
+
+#########################################
+# Prowise
+#########################################
+sensor:modalias:acpi:SMO8500*:dmi:*:svnProwise:pnPT301:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
+
 #########################################
 # Teclast
 #########################################
index c80d22258a35fd675368a9a3b18754c668ec5a49..61ca0ca6e05e24accf9404bed9297075fabc51c6 100755 (executable)
@@ -17,7 +17,6 @@ TAB = White('\t', exact=1).suppress()
 COMMENTLINE = pythonStyleComment + EOL
 EMPTYLINE = LineEnd()
 text_eol = lambda name: Regex(r'[^\n]+')(name) + EOL
-# text_eol = lambda name: Word(printables + ' ' + '®üäßçõãİó ×²⁶´‐“\u200E\u200B')(name) + EOL
 
 def klass_grammar():
     klass_line = Literal('C ').suppress() + NUM2('klass') + text_eol('text')
index 4900a2577871cc9f225d16af44c1b849c248dd20..d84fba2221ade7a8ac3049a16a9224636ed18dca 100755 (executable)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#  SPDX-License-Identifier: MIT
+# SPDX-License-Identifier: MIT
 #
 # This file is distributed under the MIT license, see below.
 #
@@ -30,8 +29,7 @@ import sys
 import os
 
 try:
-    from pyparsing import (Word, White, Literal, ParserElement, Regex,
-                           LineStart, LineEnd,
+    from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd,
                            OneOrMore, Combine, Or, Optional, Suppress, Group,
                            nums, alphanums, printables,
                            stringEnd, pythonStyleComment, QuotedString,
index 6115b4e8cf9be0595c3f0a537b10c18ae65773fa..c252bd370354a151330a72fa93cd29df78aef24b 100644 (file)
@@ -7,7 +7,7 @@
             (eval . (c-set-offset 'arglist-intro '++))
             (eval . (c-set-offset 'arglist-close 0))))
  (nxml-mode . ((nxml-child-indent . 2)
-               (fill-column . 119)))
+               (fill-column . 109)))
  (meson-mode . ((meson-indent-basic . 8)))
  (nil . ((indent-tabs-mode . nil)
          (tab-width . 8)
index f0f03a29b21fa47d08eeb9bf10431b7230faf21e..9167993012a2f4e4248d4601825956c353453a97 100644 (file)
@@ -52,7 +52,7 @@
 
       <listitem><para>Structured system log messages via the native
       Journal API, see
-      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>4</manvolnum></citerefentry></para></listitem>
+      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry></para></listitem>
 
       <listitem><para>Standard output and standard error of service units. For further details see
       below.</para></listitem>
@@ -303,7 +303,7 @@ systemd-tmpfiles --create --prefix /var/log/journal</programlisting>
       <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-coredump</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='die-net'><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>4</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
       <command>pydoc systemd.journal</command>
     </para>
   </refsect1>
index daee201eeb41d34a693cbc3aa0faf6848337b10f..abd43ee68481c35268922cb2f767cb4e0e8289fe 100644 (file)
         for details.</para></listitem>
       </varlistentry>
 
-      <varlistentry>
+      <varlistentry id='device-timeout'>
         <term><option>x-systemd.device-timeout=</option></term>
 
         <listitem><para>Configure how long systemd should wait for a
       <varlistentry>
         <term><option>x-systemd.makefs</option></term>
 
-        <listitem><para>The file system or swap structure will be initialized
+        <listitem><para>The file system will be initialized
         on the device. If the device is not "empty", i.e. it contains any signature,
         the operation will be skipped. It is hence expected that this option
         remains set even after the device has been initalized.</para>
index f17a6a961905a81aadc794d282e7beba1cbe8d12..67ccc66dd8ed09ffd17378504c23b6140453ece9 100644 (file)
           applicable to SIT tunnels.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>ISATAP=</varname></term>
+        <listitem>
+          <para>Takes a boolean. If set, configures the tunnel as Intra-Site Automatic Tunnel Addressing Protocol (ISATAP) tunnel.
+          Only applicable to SIT tunnels. When unset, the kernel's default will be used.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>SerializeTunneledPackets=</varname></term>
         <listitem>
index 229449c5ac569c843c199737420dc0c3d7e9ce73..865b46f403e88ced9d9c19cfd89f5dd3c53a42e0 100644 (file)
       </variablelist>
   </refsect1>
 
+  <refsect1>
+    <title>[Neighbor] Section Options</title>
+      <para>A <literal>[Neighbor]</literal> section accepts the
+      following keys. The neighbor section adds a permanent, static
+      entry to the neighbor table (IPv6) or ARP table (IPv4) for
+      the given hardware address on the links matched for the network.
+      Specify several <literal>[Neighbor]</literal> sections to configure
+      several static neighbors.</para>
+
+      <variablelist class='network-directives'>
+        <varlistentry>
+          <term><varname>Address=</varname></term>
+          <listitem>
+            <para>The IP address of the neighbor.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>MACAddress=</varname></term>
+          <listitem>
+            <para>The hardware address of the neighbor.</para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+  </refsect1>
+
     <refsect1>
     <title>[IPv6AddressLabel] Section Options</title>
 
             Defaults to unset.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>InvertRule=</varname></term>
+          <listitem>
+            <para>A boolean. Specifies wheather the rule to be inverted. Defaults to false.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>MulticastToUnicast=</varname></term>
+          <listitem>
+            <para>Takes a boolean. Multicast to unicast works on top of the multicast snooping feature of
+            the bridge. Which means unicast copies are only delivered to hosts which are interested in it.
+            When unset, the kernel's default will be used.
+            </para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>HairPin=</varname></term>
           <listitem>
index 998a047ec50a9512c2c9b1bd96a430e90aa01031..073c2b3a27c1412b3bc6b8d467322fe07c19b6bc 100644 (file)
@@ -6,7 +6,9 @@
   SPDX-License-Identifier: LGPL-2.1+
 -->
 
-<refentry id="systemd.swap">
+<refentry id="systemd.swap"
+          xmlns:xi="http://www.w3.org/2001/XInclude">
+
   <refentryinfo>
     <title>systemd.swap</title>
     <productname>systemd</productname>
         successfully.</para>
         </listitem>
       </varlistentry>
+
+      <xi:include href="systemd.mount.xml" xpointer="device-timeout" />
+
+      <varlistentry>
+        <term><option>x-systemd.makefs</option></term>
+
+        <listitem><para>The swap structure will be initialized on the device. If the device is not
+        "empty", i.e. it contains any signature, the operation will be skipped. It is hence expected
+        that this option remains set even after the device has been initalized.</para>
+
+        <para>Note that this option can only be used in <filename>/etc/fstab</filename>, and will be
+        ignored when part of the <varname>Options=</varname> setting in a unit file.</para>
+
+        <para>See
+        <citerefentry><refentrytitle>systemd-mkswap@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        and the discussion of
+        <citerefentry project='man-pages'><refentrytitle>wipefs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+        in <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+        </para></listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index 5fb090f6d35e8b38d566e05479f3a3458eb3a519..26d215e3cc4e83616f46d519d67c06544ac3ca14 100644 (file)
       <varlistentry>
         <term><varname>JobTimeoutSec=</varname></term>
         <term><varname>JobRunningTimeoutSec=</varname></term>
-        <term><varname>JobTimeoutAction=</varname></term>
-        <term><varname>JobTimeoutRebootArgument=</varname></term>
 
         <listitem><para>When a job for this unit is queued, a time-out <varname>JobTimeoutSec=</varname> may be
         configured. Similarly, <varname>JobRunningTimeoutSec=</varname> starts counting when the queued job is actually
         no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific
         timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however
         is useful to abort only the job waiting for the unit state to change.</para>
+        </listitem>
+      </varlistentry>
 
-        <para><varname>JobTimeoutAction=</varname> optionally configures an additional action to take when the time-out
-        is hit. It takes the same values as <varname>StartLimitAction=</varname>. Defaults to <option>none</option>.
+      <varlistentry>
+        <term><varname>JobTimeoutAction=</varname></term>
+        <term><varname>JobTimeoutRebootArgument=</varname></term>
+
+        <listitem><para><varname>JobTimeoutAction=</varname> optionally configures an additional action to take when
+        the time-out is hit, see description of <varname>JobTimeoutSec=</varname> and
+        <varname>JobRunningTimeoutSec=</varname> above. It takes the same values as
+        <varname>StartLimitAction=</varname>. Defaults to <option>none</option>.
         <varname>JobTimeoutRebootArgument=</varname> configures an optional reboot string to pass to the
-        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry>
-        system call.</para></listitem>
+        <citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call.
+        </para></listitem>
       </varlistentry>
 
       <varlistentry>
index a8bc752f1e98a8abc6969e4df9cd814e0be5a8a9..6c8c0c14c66b7b2bef6dbeb2e89be5799e7bd032 100644 (file)
@@ -30,8 +30,13 @@ __get_machines() {
         machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
 }
 
+__get_services() {
+        systemctl list-units --no-legend --no-pager -t service --all $1 | \
+                { while read -r a b c; do [[ $b == "loaded" ]]; echo " $a"; done }
+}
+
 _systemd_analyze() {
-        local i verb comps
+        local i verb comps mode
         local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
 
         local -A OPTS=(
@@ -50,6 +55,7 @@ _systemd_analyze() {
                 [SECCOMP_FILTER]='syscall-filter'
                 [SERVICE_WATCHDOGS]='service-watchdogs'
                 [CAT_CONFIG]='cat-config'
+                [SECURITY]='security'
         )
 
         local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf
@@ -148,6 +154,18 @@ _systemd_analyze() {
                         comps="$CONFIGS $( compgen -A file -- "$cur" )"
                         compopt -o filenames
                 fi
+
+        elif __contains_word "$verb" ${VERBS[SECURITY]}; then
+                if [[ $cur = -* ]]; then
+                        comps='--help --version --no-pager --system --user -H --host -M --machine'
+                else
+                        if __contains_word "--user" ${COMP_WORDS[*]}; then
+                                mode=--user
+                        else
+                                mode=--system
+                        fi
+                        comps=$( __get_services $mode )
+                fi
         fi
 
         COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
index 912772d590c974547dc72fd3e3bad7997b0eee8a..9a83bc7f24378e9f0484a2e1007c3892af71c76a 100644 (file)
@@ -249,7 +249,7 @@ static int fork_and_exec_process(const char* child, char** argv, char **env, int
         if (!joined)
                 return log_oom();
 
-        r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
+        r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &child_pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index 8652863cac5cf40a5d02bcf7ef2abc79b7db81c8..b6e2486b67b393f6c65edb39c8552784a94931f5 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "arphrd-list.h"
 #include "macro.h"
+#include "missing_network.h"
 
 static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
 
index 2fae4da15bcde170de90f97a69cf39455dcbf172..c06f2fac7e80dc8f44996d711a7bae5537ffc9c5 100644 (file)
@@ -114,7 +114,7 @@ FILE* safe_fclose(FILE *f) {
         if (f) {
                 PROTECT_ERRNO;
 
-                assert_se(fclose_nointr(f) != EBADF);
+                assert_se(fclose_nointr(f) != -EBADF);
         }
 
         return NULL;
index 39e2dad5e7ab205ecec469df53677243e87f4b09..5bf244c49d1f58dc04fbae2012c6bb77f806ec74 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 set -eu
 
-$1 -E -dM -include sys/socket.h - </dev/null | \
+$1 -E -dM -include sys/socket.h -include "$2" -include "$3" - </dev/null | \
         grep -Ev 'AF_UNSPEC|AF_MAX' | \
         awk '/^#define[ \t]+AF_[^ \t]+[ \t]+[AP]F_[^ \t]/ { print $2; }'
index e4e7271c4de01add7153f75ad1fbbaaa756df292..e6e874a8fd06d0b4c83a0a4f50aef3960936c1c6 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 set -eu
 
-$1 -dM -include net/if_arp.h - </dev/null | \
+$1 -dM -include net/if_arp.h -include "$2" -include "$3" - </dev/null | \
         awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
         sed -e 's/ARPHRD_//'
index 3b7971fe842f987800a2cfd8b1c1a5f41923060d..1971e912db4f497e676af561733f98286397e4ad 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <assert.h>
+#include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <sys/param.h>
index 153a38f9d050074726c194aa15b528594b496856..23b5e75bd8ae3e56ebb175708e49cc2b499e7217 100644 (file)
@@ -91,23 +91,35 @@ basic_sources = files('''
         memfd-util.h
         mempool.c
         mempool.h
+        missing.h
+        missing_audit.h
         missing_btrfs.h
         missing_btrfs_tree.h
         missing_capability.h
+        missing_drm.h
         missing_ethtool.h
+        missing_fcntl.h
         missing_fib_rules.h
         missing_fou.h
+        missing_fs.h
         missing_if_bridge.h
         missing_if_link.h
         missing_if_tunnel.h
         missing_input.h
         missing_keyctl.h
         missing_magic.h
+        missing_mman.h
         missing_network.h
         missing_prctl.h
+        missing_random.h
+        missing_resource.h
+        missing_sched.h
         missing_securebits.h
+        missing_socket.h
         missing_stat.h
+        missing_stdlib.h
         missing_syscall.h
+        missing_timerfd.h
         missing_type.h
         missing_vxcan.h
         mkdir-label.c
@@ -139,6 +151,8 @@ basic_sources = files('''
         refcnt.h
         replace-var.c
         replace-var.h
+        rlimit-util.c
+        rlimit-util.h
         rm-rf.c
         rm-rf.h
         selinux-util.c
@@ -197,27 +211,30 @@ basic_sources = files('''
         xattr-util.h
 '''.split())
 
-missing_h = files('missing.h')
+missing_audit_h = files('missing_audit.h')
+missing_capability_h = files('missing_capability.h')
+missing_network_h = files('missing_network.h')
+missing_socket_h = files('missing_socket.h')
 
 generate_af_list = find_program('generate-af-list.sh')
 af_list_txt = custom_target(
         'af-list.txt',
         output : 'af-list.txt',
-        command : [generate_af_list, cpp],
+        command : [generate_af_list, cpp, config_h, missing_socket_h],
         capture : true)
 
 generate_arphrd_list = find_program('generate-arphrd-list.sh')
 arphrd_list_txt = custom_target(
         'arphrd-list.txt',
         output : 'arphrd-list.txt',
-        command : [generate_arphrd_list, cpp],
+        command : [generate_arphrd_list, cpp, config_h, missing_network_h],
         capture : true)
 
 generate_cap_list = find_program('generate-cap-list.sh')
 cap_list_txt = custom_target(
         'cap-list.txt',
         output : 'cap-list.txt',
-        command : [generate_cap_list, cpp, config_h, missing_h],
+        command : [generate_cap_list, cpp, config_h, missing_capability_h],
         capture : true)
 
 generate_errno_list = find_program('generate-errno-list.sh')
@@ -266,7 +283,7 @@ foreach item : [['af',     af_list_txt,     'af',         ''],
         generated_gperf_headers += [target1, target2]
 endforeach
 
-basic_sources += [missing_h] + generated_gperf_headers
+basic_sources += generated_gperf_headers
 basic_gcrypt_sources = files(
         'gcrypt-util.c',
         'gcrypt-util.h')
index e3ee46bccea3a407dcbe6e363242824dc933cf2c..5067c8fd009a80bc426e494c57da523eb79d96bd 100644 (file)
 
 /* Missing glibc definitions to access certain kernel APIs */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <linux/audit.h>
-#include <linux/falloc.h>
-#include <linux/oom.h>
-#include <net/ethernet.h>
-#include <stdlib.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#if HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#ifdef ARCH_MIPS
-#include <asm/sgidefs.h>
-#endif
-
-#if HAVE_LINUX_VM_SOCKETS_H
-#include <linux/vm_sockets.h>
-#else
-#define VMADDR_CID_ANY -1U
-struct sockaddr_vm {
-        unsigned short svm_family;
-        unsigned short svm_reserved1;
-        unsigned int svm_port;
-        unsigned int svm_cid;
-        unsigned char svm_zero[sizeof(struct sockaddr) -
-                               sizeof(unsigned short) -
-                               sizeof(unsigned short) -
-                               sizeof(unsigned int) -
-                               sizeof(unsigned int)];
-};
-#endif /* !HAVE_LINUX_VM_SOCKETS_H */
-
-#ifndef RLIMIT_RTTIME
-#define RLIMIT_RTTIME 15
-#endif
-
-/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
-#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS)
-
-#ifndef F_LINUX_SPECIFIC_BASE
-#define F_LINUX_SPECIFIC_BASE 1024
-#endif
-
-#ifndef F_SETPIPE_SZ
-#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
-#endif
-
-#ifndef F_GETPIPE_SZ
-#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
-#endif
-
-#ifndef F_ADD_SEALS
-#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
-#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
-
-#define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
-#define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
-#define F_SEAL_GROW     0x0004  /* prevent file from growing */
-#define F_SEAL_WRITE    0x0008  /* prevent writes */
-#endif
-
-#ifndef F_OFD_GETLK
-#define F_OFD_GETLK     36
-#define F_OFD_SETLK     37
-#define F_OFD_SETLKW    38
-#endif
-
-#ifndef MFD_ALLOW_SEALING
-#define MFD_ALLOW_SEALING 0x0002U
-#endif
-
-#ifndef MFD_CLOEXEC
-#define MFD_CLOEXEC 0x0001U
-#endif
-
-#ifndef IP_FREEBIND
-#define IP_FREEBIND 15
-#endif
-
-#ifndef OOM_SCORE_ADJ_MIN
-#define OOM_SCORE_ADJ_MIN (-1000)
-#endif
-
-#ifndef OOM_SCORE_ADJ_MAX
-#define OOM_SCORE_ADJ_MAX 1000
-#endif
-
-#ifndef AUDIT_SERVICE_START
-#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
-#endif
-
-#ifndef AUDIT_SERVICE_STOP
-#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
-#endif
-
-#ifndef TIOCVHANGUP
-#define TIOCVHANGUP 0x5437
-#endif
-
-#ifndef IP_TRANSPARENT
-#define IP_TRANSPARENT 19
-#endif
-
-#ifndef SOL_NETLINK
-#define SOL_NETLINK 270
-#endif
-
-#ifndef NETLINK_LIST_MEMBERSHIPS
-#define NETLINK_LIST_MEMBERSHIPS 9
-#endif
-
-#ifndef SOL_SCTP
-#define SOL_SCTP 132
-#endif
-
-#ifndef GRND_NONBLOCK
-#define GRND_NONBLOCK 0x0001
-#endif
-
-#ifndef GRND_RANDOM
-#define GRND_RANDOM 0x0002
-#endif
-
-#ifndef FS_NOCOW_FL
-#define FS_NOCOW_FL 0x00800000
-#endif
-
-#ifndef CLONE_NEWCGROUP
-#define CLONE_NEWCGROUP 0x02000000
-#endif
-
-#ifndef MS_MOVE
-#define MS_MOVE 8192
-#endif
-
-#ifndef MS_REC
-#define MS_REC 16384
-#endif
-
-#ifndef MS_PRIVATE
-#define MS_PRIVATE      (1<<18)
-#endif
-
-#ifndef MS_REC
-#define MS_REC          (1<<19)
-#endif
-
-#ifndef MS_SHARED
-#define MS_SHARED       (1<<20)
-#endif
-
-#ifndef MS_RELATIME
-#define MS_RELATIME     (1<<21)
-#endif
-
-#ifndef MS_KERNMOUNT
-#define MS_KERNMOUNT    (1<<22)
-#endif
-
-#ifndef MS_I_VERSION
-#define MS_I_VERSION    (1<<23)
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME  (1<<24)
-#endif
-
-#ifndef MS_LAZYTIME
-#define MS_LAZYTIME     (1<<25)
-#endif
-
-#ifndef SCM_SECURITY
-#define SCM_SECURITY 0x03
-#endif
-
-#ifndef DM_DEFERRED_REMOVE
-#define DM_DEFERRED_REMOVE (1 << 17)
-#endif
-
-#ifndef MAX_HANDLE_SZ
-#define MAX_HANDLE_SZ 128
-#endif
-
-#if ! HAVE_SECURE_GETENV
-#  if HAVE___SECURE_GETENV
-#    define secure_getenv __secure_getenv
-#  else
-#    error "neither secure_getenv nor __secure_getenv are available"
-#  endif
-#endif
-
-#ifndef CIFS_MAGIC_NUMBER
-#  define CIFS_MAGIC_NUMBER 0xFF534D42
-#endif
-
-#ifndef TFD_TIMER_CANCEL_ON_SET
-#  define TFD_TIMER_CANCEL_ON_SET (1 << 1)
-#endif
-
-#ifndef SO_REUSEPORT
-#  define SO_REUSEPORT 15
-#endif
-
-#ifndef SO_PEERGROUPS
-#  define SO_PEERGROUPS 59
-#endif
-
-#ifndef DRM_IOCTL_SET_MASTER
-#  define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
-#endif
-
-#ifndef DRM_IOCTL_DROP_MASTER
-#  define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
-#endif
-
-/* The precise definition of __O_TMPFILE is arch specific; use the
- * values defined by the kernel (note: some are hexa, some are octal,
- * duplicated as-is from the kernel definitions):
- * - alpha, parisc, sparc: each has a specific value;
- * - others: they use the "generic" value.
- */
-
-#ifndef __O_TMPFILE
-#if defined(__alpha__)
-#define __O_TMPFILE     0100000000
-#elif defined(__parisc__) || defined(__hppa__)
-#define __O_TMPFILE     0400000000
-#elif defined(__sparc__) || defined(__sparc64__)
-#define __O_TMPFILE     0x2000000
-#else
-#define __O_TMPFILE     020000000
-#endif
-#endif
-
-/* a horrid kludge trying to make sure that this will fail on old kernels */
-#ifndef O_TMPFILE
-#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#endif
-
-#ifndef BPF_XOR
-#define BPF_XOR 0xa0
-#endif
-
-/* Note that LOOPBACK_IFINDEX is currently not exported by the
- * kernel/glibc, but hardcoded internally by the kernel.  However, as
- * it is exported to userspace indirectly via rtnetlink and the
- * ioctls, and made use of widely we define it here too, in a way that
- * is compatible with the kernel's internal definition. */
-#ifndef LOOPBACK_IFINDEX
-#define LOOPBACK_IFINDEX 1
-#endif
-
-#ifndef MAX_AUDIT_MESSAGE_LENGTH
-#define MAX_AUDIT_MESSAGE_LENGTH 8970
-#endif
-
-#ifndef AUDIT_NLGRP_MAX
-#define AUDIT_NLGRP_READLOG 1
-#endif
-
-#ifndef RENAME_NOREPLACE
-#define RENAME_NOREPLACE (1 << 0)
-#endif
-
-#ifndef KCMP_FILE
-#define KCMP_FILE 0
-#endif
-
-#ifndef ETHERTYPE_LLDP
-#define ETHERTYPE_LLDP 0x88cc
-#endif
-
-#ifndef SOL_ALG
-#define SOL_ALG 279
-#endif
-
-#ifndef AF_VSOCK
-#define AF_VSOCK 40
-#endif
-
-#ifndef EXT4_IOC_RESIZE_FS
-#  define EXT4_IOC_RESIZE_FS              _IOW('f', 16, __u64)
-#endif
-
-#ifndef NS_GET_NSTYPE
-#define NS_GET_NSTYPE _IO(0xb7, 0x3)
-#endif
-
-#ifndef FALLOC_FL_KEEP_SIZE
-#define FALLOC_FL_KEEP_SIZE 0x01
-#endif
-
-#ifndef FALLOC_FL_PUNCH_HOLE
-#define FALLOC_FL_PUNCH_HOLE 0x02
-#endif
-
-#ifndef PF_KTHREAD
-#define PF_KTHREAD 0x00200000
-#endif
-
-/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
- * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
- * name nor any other. */
-#ifndef TASK_COMM_LEN
-#define TASK_COMM_LEN 16
-#endif
-
+#include "missing_audit.h"
 #include "missing_btrfs_tree.h"
 #include "missing_capability.h"
+#include "missing_drm.h"
+#include "missing_fcntl.h"
+#include "missing_fs.h"
 #include "missing_input.h"
 #include "missing_magic.h"
+#include "missing_mman.h"
 #include "missing_network.h"
 #include "missing_prctl.h"
+#include "missing_random.h"
+#include "missing_resource.h"
+#include "missing_sched.h"
+#include "missing_socket.h"
+#include "missing_stdlib.h"
+#include "missing_timerfd.h"
 #include "missing_type.h"
 
 #include "missing_syscall.h"
diff --git a/src/basic/missing_audit.h b/src/basic/missing_audit.h
new file mode 100644 (file)
index 0000000..b00d537
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <linux/audit.h>
+
+#if HAVE_AUDIT
+#include <libaudit.h>
+#endif
+
+#ifndef AUDIT_SERVICE_START
+#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
+#endif
+
+#ifndef AUDIT_SERVICE_STOP
+#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
+#endif
+
+#ifndef MAX_AUDIT_MESSAGE_LENGTH
+#define MAX_AUDIT_MESSAGE_LENGTH 8970
+#endif
+
+#ifndef AUDIT_NLGRP_MAX
+#define AUDIT_NLGRP_READLOG 1
+#endif
diff --git a/src/basic/missing_drm.h b/src/basic/missing_drm.h
new file mode 100644 (file)
index 0000000..a64f74e
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#ifndef DRM_IOCTL_SET_MASTER
+#define DRM_IOCTL_SET_MASTER _IO('d', 0x1e)
+#endif
+
+#ifndef DRM_IOCTL_DROP_MASTER
+#define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f)
+#endif
diff --git a/src/basic/missing_fcntl.h b/src/basic/missing_fcntl.h
new file mode 100644 (file)
index 0000000..5d1c635
--- /dev/null
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <fcntl.h>
+
+#ifndef F_LINUX_SPECIFIC_BASE
+#define F_LINUX_SPECIFIC_BASE 1024
+#endif
+
+#ifndef F_SETPIPE_SZ
+#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
+#endif
+
+#ifndef F_GETPIPE_SZ
+#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8)
+#endif
+
+#ifndef F_ADD_SEALS
+#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
+
+#define F_SEAL_SEAL     0x0001  /* prevent further seals from being set */
+#define F_SEAL_SHRINK   0x0002  /* prevent file from shrinking */
+#define F_SEAL_GROW     0x0004  /* prevent file from growing */
+#define F_SEAL_WRITE    0x0008  /* prevent writes */
+#endif
+
+#ifndef F_OFD_GETLK
+#define F_OFD_GETLK     36
+#define F_OFD_SETLK     37
+#define F_OFD_SETLKW    38
+#endif
+
+#ifndef MAX_HANDLE_SZ
+#define MAX_HANDLE_SZ 128
+#endif
+
+/* The precise definition of __O_TMPFILE is arch specific; use the
+ * values defined by the kernel (note: some are hexa, some are octal,
+ * duplicated as-is from the kernel definitions):
+ * - alpha, parisc, sparc: each has a specific value;
+ * - others: they use the "generic" value.
+ */
+
+#ifndef __O_TMPFILE
+#if defined(__alpha__)
+#define __O_TMPFILE     0100000000
+#elif defined(__parisc__) || defined(__hppa__)
+#define __O_TMPFILE     0400000000
+#elif defined(__sparc__) || defined(__sparc64__)
+#define __O_TMPFILE     0x2000000
+#else
+#define __O_TMPFILE     020000000
+#endif
+#endif
+
+/* a horrid kludge trying to make sure that this will fail on old kernels */
+#ifndef O_TMPFILE
+#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
+#endif
diff --git a/src/basic/missing_fs.h b/src/basic/missing_fs.h
new file mode 100644 (file)
index 0000000..48c1af0
--- /dev/null
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/* linux/fs.h */
+#ifndef RENAME_NOREPLACE /* 0a7c3937a1f23f8cb5fc77ae01661e9968a51d0c (3.15) */
+#define RENAME_NOREPLACE (1 << 0)
+#endif
+
+/* linux/fs.h or sys/mount.h */
+#ifndef MS_MOVE
+#define MS_MOVE 8192
+#endif
+
+#ifndef MS_REC
+#define MS_REC 16384
+#endif
+
+#ifndef MS_PRIVATE
+#define MS_PRIVATE      (1<<18)
+#endif
+
+#ifndef MS_SLAVE
+#define MS_SLAVE        (1<<19)
+#endif
+
+#ifndef MS_SHARED
+#define MS_SHARED       (1<<20)
+#endif
+
+#ifndef MS_RELATIME
+#define MS_RELATIME     (1<<21)
+#endif
+
+#ifndef MS_KERNMOUNT
+#define MS_KERNMOUNT    (1<<22)
+#endif
+
+#ifndef MS_I_VERSION
+#define MS_I_VERSION    (1<<23)
+#endif
+
+#ifndef MS_STRICTATIME
+#define MS_STRICTATIME  (1<<24)
+#endif
+
+#ifndef MS_LAZYTIME
+#define MS_LAZYTIME     (1<<25)
+#endif
+
+/* Not exposed yet. Defined at fs/ext4/ext4.h */
+#ifndef EXT4_IOC_RESIZE_FS
+#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64)
+#endif
+
+/* Not exposed yet. Defined at fs/cifs/cifsglob.h */
+#ifndef CIFS_MAGIC_NUMBER
+#define CIFS_MAGIC_NUMBER 0xFF534D42
+#endif
+
+/* linux/nsfs.h */
+#ifndef NS_GET_NSTYPE /* d95fa3c76a66b6d76b1e109ea505c55e66360f3c (4.11) */
+#define NS_GET_NSTYPE _IO(0xb7, 0x3)
+#endif
index 93cdf9a310beec1b6d0ec3908f671f650733f191..b91ccb6485a88fe28493b13b447bf14d4836eba1 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <linux/input.h>
+#include <linux/types.h>
 
 /* linux@c7dc65737c9a607d3e6f8478659876074ad129b8 (3.12) */
 #ifndef EVIOCREVOKE
@@ -11,9 +12,9 @@
 /* linux@06a16293f71927f756dcf37558a79c0b05a91641 (4.4) */
 #ifndef EVIOCSMASK
 struct input_mask {
-        uint32_t type;
-        uint32_t codes_size;
-        uint64_t codes_ptr;
+        __u32 type;
+        __u32 codes_size;
+        __u64 codes_ptr;
 };
 
 #define EVIOCGMASK _IOR('E', 0x92, struct input_mask)
diff --git a/src/basic/missing_mman.h b/src/basic/missing_mman.h
new file mode 100644 (file)
index 0000000..7ff12f7
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/mman.h>
+
+#ifndef MFD_ALLOW_SEALING
+#define MFD_ALLOW_SEALING 0x0002U
+#endif
+
+#ifndef MFD_CLOEXEC
+#define MFD_CLOEXEC 0x0001U
+#endif
index cba236b64db13d06004c9f50728cdf97489ce394..59a8cd2c60892f43b5791f781b0f3f96955053da 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/loop.h>
 #include <linux/rtnetlink.h>
+#include <net/ethernet.h>
 
 #include "missing_ethtool.h"
 #include "missing_fib_rules.h"
 #define IFA_F_MCAUTOJOIN 0x400
 #endif
 
+/* if_arp.h */
+#ifndef ARPHRD_IP6GRE
+#define ARPHRD_IP6GRE 823
+#endif
+
 /* if_bonding.h */
 #ifndef BOND_XMIT_POLICY_ENCAP23
 #define BOND_XMIT_POLICY_ENCAP23 3
 #define NET_NAME_RENAMED 4
 #endif
 
+/* netlink.h */
+#ifndef NETLINK_LIST_MEMBERSHIPS /* b42be38b2778eda2237fc759e55e3b698b05b315 (4.2) */
+#define NETLINK_LIST_MEMBERSHIPS 9
+#endif
+
 /* rtnetlink.h */
 #ifndef RTA_PREF
 #define RTA_PREF 20
 #ifndef RTA_EXPIRES
 #define RTA_EXPIRES 23
 #endif
+
+/* Note that LOOPBACK_IFINDEX is currently not exported by the
+ * kernel/glibc, but hardcoded internally by the kernel.  However, as
+ * it is exported to userspace indirectly via rtnetlink and the
+ * ioctls, and made use of widely we define it here too, in a way that
+ * is compatible with the kernel's internal definition. */
+#ifndef LOOPBACK_IFINDEX
+#define LOOPBACK_IFINDEX 1
+#endif
+
+/* Not exposed yet. Similar values are defined in net/ethernet.h */
+#ifndef ETHERTYPE_LLDP
+#define ETHERTYPE_LLDP 0x88cc
+#endif
diff --git a/src/basic/missing_random.h b/src/basic/missing_random.h
new file mode 100644 (file)
index 0000000..2e76031
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#if USE_SYS_RANDOM_H
+#  include <sys/random.h>
+#else
+#  include <linux/random.h>
+#endif
+
+#ifndef GRND_NONBLOCK
+#define GRND_NONBLOCK 0x0001
+#endif
+
+#ifndef GRND_RANDOM
+#define GRND_RANDOM 0x0002
+#endif
diff --git a/src/basic/missing_resource.h b/src/basic/missing_resource.h
new file mode 100644 (file)
index 0000000..22ba8ab
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/resource.h>
+
+#ifndef RLIMIT_RTTIME
+#define RLIMIT_RTTIME 15
+#endif
+
+/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */
+#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS)
diff --git a/src/basic/missing_sched.h b/src/basic/missing_sched.h
new file mode 100644 (file)
index 0000000..baa3913
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sched.h>
+
+#ifndef CLONE_NEWCGROUP
+#define CLONE_NEWCGROUP 0x02000000
+#endif
+
+/* Not exposed yet. Defined at include/linux/sched.h */
+#ifndef PF_KTHREAD
+#define PF_KTHREAD 0x00200000
+#endif
+
+/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same
+ * name, which we need in userspace at various places but is not defined in userspace currently, neither under this
+ * name nor any other. */
+/* Not exposed yet. Defined at include/linux/sched.h */
+#ifndef TASK_COMM_LEN
+#define TASK_COMM_LEN 16
+#endif
diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h
new file mode 100644 (file)
index 0000000..a5fd457
--- /dev/null
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/socket.h>
+
+#if HAVE_LINUX_VM_SOCKETS_H
+#include <linux/vm_sockets.h>
+#else
+#define VMADDR_CID_ANY -1U
+struct sockaddr_vm {
+        unsigned short svm_family;
+        unsigned short svm_reserved1;
+        unsigned int svm_port;
+        unsigned int svm_cid;
+        unsigned char svm_zero[sizeof(struct sockaddr) -
+                               sizeof(unsigned short) -
+                               sizeof(unsigned short) -
+                               sizeof(unsigned int) -
+                               sizeof(unsigned int)];
+};
+#endif /* !HAVE_LINUX_VM_SOCKETS_H */
+
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+
+#ifndef SO_REUSEPORT
+#define SO_REUSEPORT 15
+#endif
+
+#ifndef SO_PEERGROUPS
+#define SO_PEERGROUPS 59
+#endif
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+/* Not exposed yet. Defined in include/linux/socket.h. */
+#ifndef SOL_SCTP
+#define SOL_SCTP 132
+#endif
+
+/* Not exposed yet. Defined in include/linux/socket.h */
+#ifndef SCM_SECURITY
+#define SCM_SECURITY 0x03
+#endif
+
+/* netinet/in.h */
+#ifndef IP_FREEBIND
+#define IP_FREEBIND 15
+#endif
+
+#ifndef IP_TRANSPARENT
+#define IP_TRANSPARENT 19
+#endif
index 85f98e2690c795aae790e861072d2cca9130ca1d..5116206a2e53cdb265b7facbd21584ff908b7489 100644 (file)
 /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
 #if !HAVE_STRUCT_STATX
 struct statx_timestamp {
-        int64_t tv_sec;
-        uint32_t tv_nsec;
-        uint32_t __reserved;
+        __s64 tv_sec;
+        __u32 tv_nsec;
+        __s32 __reserved;
 };
 struct statx {
-        uint32_t stx_mask;
-        uint32_t stx_blksize;
-        uint64_t stx_attributes;
-        uint32_t stx_nlink;
-        uint32_t stx_uid;
-        uint32_t stx_gid;
-        uint16_t stx_mode;
-        uint16_t __spare0[1];
-        uint64_t stx_ino;
-        uint64_t stx_size;
-        uint64_t stx_blocks;
-        uint64_t stx_attributes_mask;
+        __u32 stx_mask;
+        __u32 stx_blksize;
+        __u64 stx_attributes;
+        __u32 stx_nlink;
+        __u32 stx_uid;
+        __u32 stx_gid;
+        __u16 stx_mode;
+        __u16 __spare0[1];
+        __u64 stx_ino;
+        __u64 stx_size;
+        __u64 stx_blocks;
+        __u64 stx_attributes_mask;
         struct statx_timestamp stx_atime;
         struct statx_timestamp stx_btime;
         struct statx_timestamp stx_ctime;
         struct statx_timestamp stx_mtime;
-        uint32_t stx_rdev_major;
-        uint32_t stx_rdev_minor;
-        uint32_t stx_dev_major;
-        uint32_t stx_dev_minor;
-        uint64_t __spare2[14];
+        __u32 stx_rdev_major;
+        __u32 stx_rdev_minor;
+        __u32 stx_dev_major;
+        __u32 stx_dev_minor;
+        __u64 __spare2[14];
 };
 #endif
 
diff --git a/src/basic/missing_stdlib.h b/src/basic/missing_stdlib.h
new file mode 100644 (file)
index 0000000..188a8d4
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdlib.h>
+
+/* stdlib.h */
+#if !HAVE_SECURE_GETENV
+#  if HAVE___SECURE_GETENV
+#    define secure_getenv __secure_getenv
+#  else
+#    error "neither secure_getenv nor __secure_getenv are available"
+#  endif
+#endif
index b009ea5bfa6904b65deedbdb0697a1cc617eab7d..d5d4b26acb3776a188329e6a863a13a7ad759975 100644 (file)
@@ -6,10 +6,20 @@
 #include <fcntl.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
+#include <unistd.h>
+
+#ifdef ARCH_MIPS
+#include <asm/sgidefs.h>
+#endif
 
 #include "missing_keyctl.h"
 #include "missing_stat.h"
 
+/* linux/kcmp.h */
+#ifndef KCMP_FILE /* 3f4994cfc15f38a3159c6e3a4b3ab2e1481a6b02 (3.19) */
+#define KCMP_FILE 0
+#endif
+
 #if !HAVE_PIVOT_ROOT
 static inline int missing_pivot_root(const char *new_root, const char *put_old) {
         return syscall(__NR_pivot_root, new_root, put_old);
@@ -257,7 +267,7 @@ static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long i
 /* ======================================================================= */
 
 #if !HAVE_KEYCTL
-static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4,unsigned long arg5) {
+static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
 #  ifdef __NR_keyctl
         return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
 #  else
diff --git a/src/basic/missing_timerfd.h b/src/basic/missing_timerfd.h
new file mode 100644 (file)
index 0000000..6b04044
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <sys/timerfd.h>
+
+#ifndef TFD_TIMER_CANCEL_ON_SET
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#endif
index 0a9f479e42a376733d8d545c7c1ec79ba7bb71fc..1e946a0bb67587e4562f7a7d396ff53da987249a 100644 (file)
@@ -98,7 +98,7 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
         if ((flags & AT_EMPTY_PATH) && isempty(filename))
                 xsprintf(path, "/proc/self/fdinfo/%i", fd);
         else {
-                subfd = openat(fd, filename, O_CLOEXEC|O_PATH);
+                subfd = openat(fd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_FOLLOW ? 0 : O_NOFOLLOW));
                 if (subfd < 0)
                         return -errno;
 
index 5b4e94c13488fef0f70cca5d1c4b6446b4cd7965..87724af693068b624a0f9f0a366404ca3597239c 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <errno.h>
 #include <inttypes.h>
+#include <linux/oom.h>
 #include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
index 981628504b3fd5edd327d41f4788d375004b2b79..5b700df33a973f42365a476494b6a5aa24d0a4ab 100644 (file)
@@ -35,6 +35,7 @@
 #include "missing.h"
 #include "process-util.h"
 #include "raw-clone.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "stat-util.h"
 #include "string-table.h"
@@ -1401,6 +1402,14 @@ int safe_fork_full(
                 }
         }
 
+        if (flags & FORK_RLIMIT_NOFILE_SAFE) {
+                r = rlimit_nofile_safe();
+                if (r < 0) {
+                        log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
+                        _exit(EXIT_FAILURE);
+                }
+        }
+
         if (ret_pid)
                 *ret_pid = getpid_cached();
 
@@ -1512,6 +1521,8 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
                 safe_close_above_stdio(fd);
         }
 
+        (void) rlimit_nofile_safe();
+
         /* Count arguments */
         va_start(ap, path);
         for (n = 0; va_arg(ap, char*); n++)
index af47513fab0f0b16ae210a5d1084de8ea3719337..496e14d3de17667217e455c43471bf9f9dd39b8c 100644 (file)
@@ -142,15 +142,16 @@ void reset_cached_pid(void);
 int must_be_root(void);
 
 typedef enum ForkFlags {
-        FORK_RESET_SIGNALS = 1 << 0,
-        FORK_CLOSE_ALL_FDS = 1 << 1,
-        FORK_DEATHSIG      = 1 << 2,
-        FORK_NULL_STDIO    = 1 << 3,
-        FORK_REOPEN_LOG    = 1 << 4,
-        FORK_LOG           = 1 << 5,
-        FORK_WAIT          = 1 << 6,
-        FORK_NEW_MOUNTNS   = 1 << 7,
-        FORK_MOUNTNS_SLAVE = 1 << 8,
+        FORK_RESET_SIGNALS      = 1 << 0, /* Reset all signal handlers and signal mask */
+        FORK_CLOSE_ALL_FDS      = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
+        FORK_DEATHSIG           = 1 << 2, /* Set PR_DEATHSIG in the child */
+        FORK_NULL_STDIO         = 1 << 3, /* Connect 0,1,2 to /dev/null */
+        FORK_REOPEN_LOG         = 1 << 4, /* Reopen log connection */
+        FORK_LOG                = 1 << 5, /* Log above LOG_DEBUG log level about failures */
+        FORK_WAIT               = 1 << 6, /* Wait until child exited */
+        FORK_NEW_MOUNTNS        = 1 << 7, /* Run child in its own mount namespace */
+        FORK_MOUNTNS_SLAVE      = 1 << 8, /* Make child's mount namespace MS_SLAVE */
+        FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
 } ForkFlags;
 
 int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
index 4a36ad51195aa9e1b54f489c63fd939e15b12561..f7decf60b6189a7206577dc44ce650b2b148273e 100644 (file)
@@ -7,7 +7,6 @@
 #include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/random.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
similarity index 94%
rename from src/shared/rlimit-util.c
rename to src/basic/rlimit-util.c
index c133f84b7e90e24c7dd10149d09188b11beeb371..74b3a023f18ab6c6fa218397a56f8447149bcd91 100644 (file)
@@ -389,3 +389,22 @@ int rlimit_nofile_bump(int limit) {
 
         return 0;
 }
+
+int rlimit_nofile_safe(void) {
+        struct rlimit rl;
+
+        /* Resets RLIMIT_NOFILE's soft limit FD_SETSIZE (i.e. 1024), for compatibility with software still using
+         * select() */
+
+        if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
+                return log_debug_errno(errno, "Failed to query RLIMIT_NOFILE: %m");
+
+        if (rl.rlim_cur <= FD_SETSIZE)
+                return 0;
+
+        rl.rlim_cur = FD_SETSIZE;
+        if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
+                return log_debug_errno(errno, "Failed to lower RLIMIT_NOFILE's soft limit to " RLIM_FMT ": %m", rl.rlim_cur);
+
+        return 1;
+}
similarity index 96%
rename from src/shared/rlimit-util.h
rename to src/basic/rlimit-util.h
index 6139af3ff50ff5fec8e5cf56bdbfc2719cd676e4..d4fca2b8556d9b00b3a080c02c11e64737dd8ccb 100644 (file)
@@ -22,3 +22,4 @@ void rlimit_free_all(struct rlimit **rl);
 #define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
 
 int rlimit_nofile_bump(int limit);
+int rlimit_nofile_safe(void);
index 37b1bca81a8e104ffea667f1265867e06a5e61ec..574d2b73f5627e8dc52194a8ac4cbd3996bfbad5 100644 (file)
@@ -1,6 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <inttypes.h>
+#include <linux/netlink.h>
+#include <linux/if_infiniband.h>
+#include <linux/if_packet.h>
 #include <netinet/ether.h>
 #include <netinet/in.h>
 #include <stdbool.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
-#include <linux/netlink.h>
-#include <linux/if_infiniband.h>
-#include <linux/if_packet.h>
 
 #include "macro.h"
-#include "missing.h"
-#include "util.h"
+#include "missing_socket.h"
+#include "sparse-endian.h"
 
 union sockaddr_union {
         /* The minimal, abstract version */
index 86e730028e4c1b7769cc0cf9e587f99d0d02bebe..c885e0a2d1a014dea069f46cf5e5e1d1537999e4 100644 (file)
@@ -18,6 +18,7 @@
 #define ANSI_MAGENTA "\x1B[0;35m"
 #define ANSI_CYAN    "\x1B[0;36m"
 #define ANSI_WHITE   "\x1B[0;37m"
+#define ANSI_GREY    "\x1B[0;2;37m"
 
 /* Bold/highlighted */
 #define ANSI_HIGHLIGHT_BLACK   "\x1B[0;1;30m"
@@ -132,6 +133,7 @@ DEFINE_ANSI_FUNC(highlight_yellow,           HIGHLIGHT_YELLOW);
 DEFINE_ANSI_FUNC(highlight_blue,             HIGHLIGHT_BLUE);
 DEFINE_ANSI_FUNC(highlight_magenta,          HIGHLIGHT_MAGENTA);
 DEFINE_ANSI_FUNC(normal,                     NORMAL);
+DEFINE_ANSI_FUNC(grey,                       GREY);
 
 DEFINE_ANSI_FUNC_UNDERLINE(underline,                  UNDERLINE, NORMAL);
 DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline,        HIGHLIGHT_UNDERLINE, HIGHLIGHT);
index 12c1fc71dfcc8c4921b3432c0e3c0ef66fc7e343..557c75debc53ba264c37159fe4020ef11ce3ec30 100644 (file)
@@ -20,7 +20,7 @@
 #include "io-util.h"
 #include "log.h"
 #include "macro.h"
-#include "missing.h"
+#include "missing_timerfd.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
index 3d8348e0b7fc0229b90a66ccae87b1b9d5eb4c85..de8010bf2e5d86865cb7fff98033423713959e77 100644 (file)
@@ -16,6 +16,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "dbus-automount.h"
+#include "dbus-unit.h"
 #include "fd-util.h"
 #include "format-util.h"
 #include "io-util.h"
@@ -237,6 +238,9 @@ static void automount_set_state(Automount *a, AutomountState state) {
         AutomountState old_state;
         assert(a);
 
+        if (a->state != state)
+                bus_unit_send_pending_change_signal(UNIT(a), false);
+
         old_state = a->state;
         a->state = state;
 
index 946c0516e142effb7a2abbffaa3421deb2a31a93..b9a611fd9e25194eeb3c53d9c3341c91a4a53009 100644 (file)
@@ -20,6 +20,7 @@
 #include "bpf-program.h"
 #include "fd-util.h"
 #include "ip-address-access.h"
+#include "missing_syscall.h"
 #include "unit.h"
 
 enum {
index 20d890b36c37685201a28e3ba5e680ade9094101..d11e58b51ddd5cde5a0a23ed8f6842416984634f 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "alloc-util.h"
 #include "dbus-job.h"
+#include "dbus-unit.h"
 #include "dbus.h"
 #include "job.h"
 #include "log.h"
@@ -173,6 +174,9 @@ void bus_job_send_change_signal(Job *j) {
 
         assert(j);
 
+        /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */
+        bus_unit_send_pending_change_signal(j->unit, true);
+
         if (j->in_dbus_queue) {
                 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
                 j->in_dbus_queue = false;
@@ -185,6 +189,21 @@ void bus_job_send_change_signal(Job *j) {
         j->sent_dbus_new_signal = true;
 }
 
+void bus_job_send_pending_change_signal(Job *j, bool including_new) {
+        assert(j);
+
+        if (!j->in_dbus_queue)
+                return;
+
+        if (!j->sent_dbus_new_signal && !including_new)
+                return;
+
+        if (MANAGER_IS_RELOADING(j->unit->manager))
+                return;
+
+        bus_job_send_change_signal(j);
+}
+
 static int send_removed_signal(sd_bus *bus, void *userdata) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
@@ -222,6 +241,9 @@ void bus_job_send_removed_signal(Job *j) {
         if (!j->sent_dbus_new_signal)
                 bus_job_send_change_signal(j);
 
+        /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */
+        bus_unit_send_pending_change_signal(j->unit, true);
+
         r = bus_foreach_bus(j->manager, j->bus_track, send_removed_signal, j);
         if (r < 0)
                 log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id);
index 3cc60f22ee069199bb545b6b8767c477389929f0..c9f6fc718719861cd6e8fae308843fcb17fc1003 100644 (file)
@@ -12,6 +12,7 @@ int bus_job_method_cancel(sd_bus_message *message, void *job, sd_bus_error *erro
 int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error);
 
 void bus_job_send_change_signal(Job *j);
+void bus_job_send_pending_change_signal(Job *j, bool including_new);
 void bus_job_send_removed_signal(Job *j);
 
 int bus_job_coldplug_bus_track(Job *j);
index 6d9b559d2c7d522ff63f561edb41b66f9fc007b6..968166ee60409dca2970490cbfa2bbfd1c85af3e 100644 (file)
@@ -662,8 +662,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
-        SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
-        SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
+        SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
         SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -675,8 +675,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
-        SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
+        SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
 
         SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -1202,6 +1202,27 @@ void bus_unit_send_change_signal(Unit *u) {
         u->sent_dbus_new_signal = true;
 }
 
+void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
+
+        /* Sends out any pending change signals, but only if they really are pending. This call is used when we are
+         * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending
+         * so that clients can follow the full state transition */
+
+        if (!u->in_dbus_queue) /* If not enqueued, don't bother */
+                return;
+
+        if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if
+                                                         * the unit appears in the new state right-away (except if the
+                                                         * caller explicitly asked us to send it anyway) */
+                return;
+
+        if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit
+                                               * when we are reloading. */
+                return;
+
+        bus_unit_send_change_signal(u);
+}
+
 static int send_removed_signal(sd_bus *bus, void *userdata) {
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
@@ -1300,6 +1321,9 @@ int bus_unit_queue_job(
         if (!path)
                 return -ENOMEM;
 
+        /* Before we send the method reply, force out the announcement JobNew for this job */
+        bus_job_send_pending_change_signal(j, true);
+
         return sd_bus_reply_method_return(message, "o", path);
 }
 
index 68eb621836b1a77d79e8f46e4d0e2c4f1c44aceb..345345e3ebadea254c0ab0bd1697b40b15fea79c 100644 (file)
@@ -11,6 +11,7 @@ extern const sd_bus_vtable bus_unit_vtable[];
 extern const sd_bus_vtable bus_unit_cgroup_vtable[];
 
 void bus_unit_send_change_signal(Unit *u);
+void bus_unit_send_pending_change_signal(Unit *u, bool including_new);
 void bus_unit_send_removed_signal(Unit *u);
 
 int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);
index 8b6126c4cfe8e95e9b0e4fb06421d6fc8e177e17..5acd9b7a7036de7652f2255de69e92f6f3eb4109 100644 (file)
@@ -6,6 +6,7 @@
 #include "alloc-util.h"
 #include "bus-error.h"
 #include "dbus-device.h"
+#include "dbus-unit.h"
 #include "device-private.h"
 #include "device-util.h"
 #include "device.h"
@@ -115,6 +116,9 @@ static void device_set_state(Device *d, DeviceState state) {
         DeviceState old_state;
         assert(d);
 
+        if (d->state != state)
+                bus_unit_send_pending_change_signal(UNIT(d), false);
+
         old_state = d->state;
         d->state = state;
 
index 16124cf28c41af5dcc5ed127440cd450ccdcc1ae..fb8c752efaa1af9815a6b5f6a232aa0eecf90e82 100644 (file)
@@ -16,7 +16,7 @@ typedef struct Manager Manager;
 #include "cgroup-util.h"
 #include "fdset.h"
 #include "list.h"
-#include "missing.h"
+#include "missing_resource.h"
 #include "namespace.h"
 #include "nsflags.h"
 
index 40be7213ebd56e5647403c66b3751d62b7da3117..af5070b8cf9acb3c3802b4fe0bdf0ef5e4be9ab5 100644 (file)
@@ -236,6 +236,9 @@ Job* job_install(Job *j) {
 
         job_add_to_gc_queue(j);
 
+        job_add_to_dbus_queue(j); /* announce this job to clients */
+        unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */
+
         return j;
 }
 
index 6d03b066847d5c45c5c52b1e64f7fc2a28a26f46..839dc062ff780700c9213beec517468c6ed66bcb 100644 (file)
@@ -236,6 +236,7 @@ _noreturn_ static void crash(int sig) {
                 else if (pid == 0) {
                         (void) setsid();
                         (void) make_console_stdio();
+                        (void) rlimit_nofile_safe();
                         (void) execle("/bin/sh", "/bin/sh", NULL, environ);
 
                         log_emergency_errno(errno, "execle() failed: %m");
@@ -1733,6 +1734,7 @@ static void do_reexecute(
         /* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
         (void) reset_all_signal_handlers();
         (void) reset_signal_mask();
+        (void) rlimit_nofile_safe();
 
         if (switch_root_init) {
                 args[0] = switch_root_init;
index 99b2aa0904c39a78782b498802ca143cb9f441f3..ead9bc1f441564993b20c7e78c22327a904a71e4 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "alloc-util.h"
 #include "dbus-mount.h"
+#include "dbus-unit.h"
 #include "device.h"
 #include "escape.h"
 #include "exit-status.h"
@@ -67,22 +68,18 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
                       MOUNT_UNMOUNTING_SIGKILL);
 }
 
-static bool mount_needs_network(const char *options, const char *fstype) {
-        if (fstab_test_option(options, "_netdev\0"))
+static bool mount_is_network(const MountParameters *p) {
+        assert(p);
+
+        if (fstab_test_option(p->options, "_netdev\0"))
                 return true;
 
-        if (fstype && fstype_is_network(fstype))
+        if (p->fstype && fstype_is_network(p->fstype))
                 return true;
 
         return false;
 }
 
-static bool mount_is_network(const MountParameters *p) {
-        assert(p);
-
-        return mount_needs_network(p->options, p->fstype);
-}
-
 static bool mount_is_loop(const MountParameters *p) {
         assert(p);
 
@@ -128,11 +125,11 @@ static bool mount_is_bound_to_device(const Mount *m) {
         return fstab_test_option(p->options, "x-systemd.device-bound\0");
 }
 
-static bool needs_quota(const MountParameters *p) {
+static bool mount_needs_quota(const MountParameters *p) {
         assert(p);
 
-        /* Quotas are not enabled on network filesystems,
-         * but we want them, for example, on storage connected via iscsi */
+        /* Quotas are not enabled on network filesystems, but we want them, for example, on storage connected via
+         * iscsi. We hence don't use mount_is_network() here, as that would also return true for _netdev devices. */
         if (p->fstype && fstype_is_network(p->fstype))
                 return false;
 
@@ -210,11 +207,9 @@ static void mount_unwatch_control_pid(Mount *m) {
 static void mount_parameters_done(MountParameters *p) {
         assert(p);
 
-        free(p->what);
-        free(p->options);
-        free(p->fstype);
-
-        p->what = p->options = p->fstype = NULL;
+        p->what = mfree(p->what);
+        p->options = mfree(p->options);
+        p->fstype = mfree(p->fstype);
 }
 
 static void mount_done(Unit *u) {
@@ -317,7 +312,7 @@ static int mount_add_mount_dependencies(Mount *m) {
 }
 
 static int mount_add_device_dependencies(Mount *m) {
-        bool device_wants_mount = false;
+        bool device_wants_mount;
         UnitDependencyMask mask;
         MountParameters *p;
         UnitDependency dep;
@@ -347,8 +342,8 @@ static int mount_add_device_dependencies(Mount *m) {
         if (path_equal(m->where, "/"))
                 return 0;
 
-        if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager))
-                device_wants_mount = true;
+        device_wants_mount =
+                mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager);
 
         /* Mount units from /proc/self/mountinfo are not bound to devices
          * by default since they're subject to races when devices are
@@ -380,7 +375,7 @@ static int mount_add_quota_dependencies(Mount *m) {
         if (!p)
                 return 0;
 
-        if (!needs_quota(p))
+        if (!mount_needs_quota(p))
                 return 0;
 
         mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
@@ -428,10 +423,10 @@ static bool mount_is_extrinsic(Mount *m) {
 }
 
 static int mount_add_default_dependencies(Mount *m) {
+        const char *after, *before;
         UnitDependencyMask mask;
-        int r;
         MountParameters *p;
-        const char *after;
+        int r;
 
         assert(m);
 
@@ -473,8 +468,15 @@ static int mount_add_default_dependencies(Mount *m) {
                         return r;
 
                 after = SPECIAL_REMOTE_FS_PRE_TARGET;
-        } else
+                before = SPECIAL_REMOTE_FS_TARGET;
+        } else {
                 after = SPECIAL_LOCAL_FS_PRE_TARGET;
+                before = SPECIAL_LOCAL_FS_TARGET;
+        }
+
+        r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+        if (r < 0)
+                return r;
 
         r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
         if (r < 0)
@@ -541,6 +543,10 @@ static int mount_add_extras(Mount *m) {
 
         assert(m);
 
+        /* Note: this call might be called after we already have been loaded once (and even when it has already been
+         * activated), in case data from /proc/self/mountinfo has changed. This means all code here needs to be ready
+         * to run with an already set up unit. */
+
         if (u->fragment_path)
                 m->from_fragment = true;
 
@@ -610,28 +616,33 @@ static int mount_load_root_mount(Unit *u) {
 
 static int mount_load(Unit *u) {
         Mount *m = MOUNT(u);
-        int r;
+        int r, q, w;
 
         assert(u);
         assert(u->load_state == UNIT_STUB);
 
         r = mount_load_root_mount(u);
-        if (r < 0)
-                return r;
 
         if (m->from_proc_self_mountinfo || u->perpetual)
-                r = unit_load_fragment_and_dropin_optional(u);
+                q = unit_load_fragment_and_dropin_optional(u);
         else
-                r = unit_load_fragment_and_dropin(u);
+                q = unit_load_fragment_and_dropin(u);
+
+        /* Add in some extras. Note we do this in all cases (even if we failed to load the unit) when announced by the
+         * kernel, because we need some things to be set up no matter what when the kernel establishes a mount and thus
+         * we need to update the state in our unit to track it. After all, consider that we don't allow changing the
+         * 'slice' field for a unit once it is active. */
+        if (u->load_state == UNIT_LOADED || m->from_proc_self_mountinfo || u->perpetual)
+                w = mount_add_extras(m);
+        else
+                w = 0;
+
         if (r < 0)
                 return r;
-
-        /* This is a new unit? Then let's add in some extras */
-        if (u->load_state == UNIT_LOADED) {
-                r = mount_add_extras(m);
-                if (r < 0)
-                        return r;
-        }
+        if (q < 0)
+                return q;
+        if (w < 0)
+                return w;
 
         return mount_verify(m);
 }
@@ -640,6 +651,9 @@ static void mount_set_state(Mount *m, MountState state) {
         MountState old_state;
         assert(m);
 
+        if (m->state != state)
+                bus_unit_send_pending_change_signal(UNIT(m), false);
+
         old_state = m->state;
         m->state = state;
 
@@ -940,7 +954,6 @@ static void mount_enter_mounting(Mount *m) {
         (void) mkdir_p_label(m->where, m->directory_mode);
 
         unit_warn_if_dir_nonempty(UNIT(m), m->where);
-
         unit_warn_leftover_processes(UNIT(m));
 
         m->control_command_id = MOUNT_EXEC_MOUNT;
@@ -1044,6 +1057,17 @@ fail:
         mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
 }
 
+static void mount_cycle_clear(Mount *m) {
+        assert(m);
+
+        /* Clear all state we shall forget for this new cycle */
+
+        m->result = MOUNT_SUCCESS;
+        m->reload_result = MOUNT_SUCCESS;
+        exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
+        UNIT(m)->reset_accounting = true;
+}
+
 static int mount_start(Unit *u) {
         Mount *m = MOUNT(u);
         int r;
@@ -1074,13 +1098,9 @@ static int mount_start(Unit *u) {
         if (r < 0)
                 return r;
 
-        m->result = MOUNT_SUCCESS;
-        m->reload_result = MOUNT_SUCCESS;
-        exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
-
-        u->reset_accounting = true;
-
+        mount_cycle_clear(m);
         mount_enter_mounting(m);
+
         return 1;
 }
 
@@ -1144,6 +1164,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
         (void) serialize_item(f, "state", mount_state_to_string(m->state));
         (void) serialize_item(f, "result", mount_result_to_string(m->result));
         (void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result));
+        (void) serialize_item_format(f, "n-retry-umount", "%u", m->n_retry_umount);
 
         if (m->control_pid > 0)
                 (void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid);
@@ -1156,6 +1177,7 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
 
 static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
         Mount *m = MOUNT(u);
+        int r;
 
         assert(u);
         assert(key);
@@ -1169,6 +1191,7 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
                         log_unit_debug(u, "Failed to parse state value: %s", value);
                 else
                         m->deserialized_state = state;
+
         } else if (streq(key, "result")) {
                 MountResult f;
 
@@ -1187,13 +1210,17 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
                 else if (f != MOUNT_SUCCESS)
                         m->reload_result = f;
 
+        } else if (streq(key, "n-retry-umount")) {
+
+                r = safe_atou(value, &m->n_retry_umount);
+                if (r < 0)
+                        log_unit_debug(u, "Failed to parse n-retry-umount value: %s", value);
+
         } else if (streq(key, "control-pid")) {
-                pid_t pid;
 
-                if (parse_pid(value, &pid) < 0)
+                if (parse_pid(value, &m->control_pid) < 0)
                         log_unit_debug(u, "Failed to parse control-pid value: %s", value);
-                else
-                        m->control_pid = pid;
+
         } else if (streq(key, "control-command")) {
                 MountExecCommand id;
 
@@ -1401,59 +1428,77 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
         return 0;
 }
 
-typedef struct {
-        bool is_mounted;
-        bool just_mounted;
-        bool just_changed;
-} MountSetupFlags;
+static int update_parameters_proc_self_mount_info(
+                Mount *m,
+                const char *what,
+                const char *options,
+                const char *fstype) {
+
+        MountParameters *p;
+        int r, q, w;
+
+        p = &m->parameters_proc_self_mountinfo;
+
+        r = free_and_strdup(&p->what, what);
+        if (r < 0)
+                return r;
+
+        q = free_and_strdup(&p->options, options);
+        if (q < 0)
+                return q;
+
+        w = free_and_strdup(&p->fstype, fstype);
+        if (w < 0)
+                return w;
+
+        return r > 0 || q > 0 || w > 0;
+}
 
 static int mount_setup_new_unit(
-                Unit *u,
+                Manager *m,
+                const char *name,
                 const char *what,
                 const char *where,
                 const char *options,
                 const char *fstype,
-                MountSetupFlags *flags) {
-
-        MountParameters *p;
+                MountProcFlags *ret_flags,
+                Unit **ret) {
 
-        assert(u);
-        assert(flags);
+        _cleanup_(unit_freep) Unit *u = NULL;
+        int r;
 
-        u->source_path = strdup("/proc/self/mountinfo");
-        MOUNT(u)->where = strdup(where);
-        if (!u->source_path || !MOUNT(u)->where)
-                return -ENOMEM;
+        assert(m);
+        assert(name);
+        assert(ret_flags);
+        assert(ret);
 
-        /* Make sure to initialize those fields before mount_is_extrinsic(). */
-        MOUNT(u)->from_proc_self_mountinfo = true;
-        p = &MOUNT(u)->parameters_proc_self_mountinfo;
+        r = unit_new_for_name(m, sizeof(Mount), name, &u);
+        if (r < 0)
+                return r;
 
-        p->what = strdup(what);
-        p->options = strdup(options);
-        p->fstype = strdup(fstype);
-        if (!p->what || !p->options || !p->fstype)
-                return -ENOMEM;
+        r = free_and_strdup(&u->source_path, "/proc/self/mountinfo");
+        if (r < 0)
+                return r;
 
-        if (!mount_is_extrinsic(MOUNT(u))) {
-                const char *target;
-                int r;
+        r = free_and_strdup(&MOUNT(u)->where, where);
+        if (r < 0)
+                return r;
 
-                target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
-                r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
-                if (r < 0)
-                        return r;
+        r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype);
+        if (r < 0)
+                return r;
 
-                r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
-                if (r < 0)
-                        return r;
-        }
+        /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load
+         * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps
+         * to.*/
+        MOUNT(u)->from_proc_self_mountinfo = true;
 
+        /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is
+         * loaded in now. */
         unit_add_to_load_queue(u);
-        flags->is_mounted = true;
-        flags->just_mounted = true;
-        flags->just_changed = true;
 
+        *ret_flags = MOUNT_PROC_IS_MOUNTED | MOUNT_PROC_JUST_MOUNTED | MOUNT_PROC_JUST_CHANGED;
+        *ret = TAKE_PTR(u);
         return 0;
 }
 
@@ -1463,11 +1508,10 @@ static int mount_setup_existing_unit(
                 const char *where,
                 const char *options,
                 const char *fstype,
-                MountSetupFlags *flags) {
+                MountProcFlags *ret_flags) {
 
-        MountParameters *p;
-        bool load_extras = false;
-        int r1, r2, r3;
+        MountProcFlags flags = MOUNT_PROC_IS_MOUNTED;
+        int r;
 
         assert(u);
         assert(flags);
@@ -1478,49 +1522,38 @@ static int mount_setup_existing_unit(
                         return -ENOMEM;
         }
 
-        /* Make sure to initialize those fields before mount_is_extrinsic(). */
-        p = &MOUNT(u)->parameters_proc_self_mountinfo;
-
-        r1 = free_and_strdup(&p->what, what);
-        r2 = free_and_strdup(&p->options, options);
-        r3 = free_and_strdup(&p->fstype, fstype);
-        if (r1 < 0 || r2 < 0 || r3 < 0)
-                return -ENOMEM;
-
-        flags->just_changed = r1 > 0 || r2 > 0 || r3 > 0;
-        flags->is_mounted = true;
-        flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->just_mounted;
-
-        MOUNT(u)->from_proc_self_mountinfo = true;
+        r = update_parameters_proc_self_mount_info(MOUNT(u), what, options, fstype);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                flags |= MOUNT_PROC_JUST_CHANGED;
 
-        if (!mount_is_extrinsic(MOUNT(u)) && mount_is_network(p)) {
-                /* _netdev option may have shown up late, or on a
-                 * remount. Add remote-fs dependencies, even though
-                 * local-fs ones may already be there.
-                 *
-                 * Note: due to a current limitation (we don't track
-                 * in the dependency "Set*" objects who created a
-                 * dependency), we can only add deps, never lose them,
-                 * until the next full daemon-reload. */
-                unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
-                load_extras = true;
+        if (!MOUNT(u)->from_proc_self_mountinfo) {
+                flags |= MOUNT_PROC_JUST_MOUNTED;
+                MOUNT(u)->from_proc_self_mountinfo = true;
         }
 
-        if (u->load_state == UNIT_NOT_FOUND) {
+        if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
+                /* The unit was previously not found or otherwise not loaded. Now that the unit shows up in
+                 * /proc/self/mountinfo we should reconsider it this, hence set it to UNIT_LOADED. */
                 u->load_state = UNIT_LOADED;
                 u->load_error = 0;
 
-                /* Load in the extras later on, after we
-                 * finished initialization of the unit */
-
-                /* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */
-                load_extras = true;
-                flags->just_changed = true;
+                flags |= MOUNT_PROC_JUST_CHANGED;
         }
 
-        if (load_extras)
-                return mount_add_extras(MOUNT(u));
+        if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) {
+                /* If things changed, then make sure that all deps are regenerated. Let's
+                 * first remove all automatic deps, and then add in the new ones. */
 
+                unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
+
+                r = mount_add_extras(MOUNT(u));
+                if (r < 0)
+                        return r;
+        }
+
+        *ret_flags = flags;
         return 0;
 }
 
@@ -1533,7 +1566,7 @@ static int mount_setup_unit(
                 bool set_flags) {
 
         _cleanup_free_ char *e = NULL;
-        MountSetupFlags flags;
+        MountProcFlags flags;
         Unit *u;
         int r;
 
@@ -1557,44 +1590,32 @@ static int mount_setup_unit(
 
         r = unit_name_from_path(where, ".mount", &e);
         if (r < 0)
-                return r;
+                return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where);
 
         u = manager_get_unit(m, e);
-        if (!u) {
-                /* First time we see this mount point meaning that it's
-                 * not been initiated by a mount unit but rather by the
-                 * sysadmin having called mount(8) directly. */
-                r = unit_new_for_name(m, sizeof(Mount), e, &u);
-                if (r < 0)
-                        goto fail;
-
-                r = mount_setup_new_unit(u, what, where, options, fstype, &flags);
-                if (r < 0)
-                        unit_free(u);
-        } else
+        if (u)
                 r = mount_setup_existing_unit(u, what, where, options, fstype, &flags);
-
+        else
+                /* First time we see this mount point meaning that it's not been initiated by a mount unit but rather
+                 * by the sysadmin having called mount(8) directly. */
+                r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u);
         if (r < 0)
-                goto fail;
-
-        if (set_flags) {
-                MOUNT(u)->is_mounted = flags.is_mounted;
-                MOUNT(u)->just_mounted = flags.just_mounted;
-                MOUNT(u)->just_changed = flags.just_changed;
-        }
+                return log_warning_errno(r, "Failed to set up mount unit: %m");
 
-        if (flags.just_changed)
+        /* If the mount changed properties or state, let's notify our clients */
+        if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED))
                 unit_add_to_dbus_queue(u);
 
+        if (set_flags)
+                MOUNT(u)->proc_flags = flags;
+
         return 0;
-fail:
-        return log_warning_errno(r, "Failed to set up mount unit: %m");
 }
 
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
         _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
-        int r = 0;
+        int r;
 
         assert(m);
 
@@ -1607,7 +1628,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         if (r < 0)
                 return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
 
-        r = 0;
         for (;;) {
                 struct libmnt_fs *fs;
                 const char *device, *path, *options, *fstype;
@@ -1636,12 +1656,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 
                 device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT);
 
-                k = mount_setup_unit(m, d, p, options, fstype, set_flags);
-                if (r == 0 && k < 0)
-                        r = k;
+                (void) mount_setup_unit(m, d, p, options, fstype, set_flags);
         }
 
-        return r;
+        return 0;
 }
 
 static void mount_shutdown(Manager *m) {
@@ -1699,7 +1717,7 @@ static void mount_enumerate_perpetual(Manager *m) {
 static bool mount_is_mounted(Mount *m) {
         assert(m);
 
-        return UNIT(m)->perpetual || m->is_mounted;
+        return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED);
 }
 
 static void mount_enumerate(Manager *m) {
@@ -1763,7 +1781,7 @@ fail:
 }
 
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
-        _cleanup_set_free_ Set *around = NULL, *gone = NULL;
+        _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
         Manager *m = userdata;
         const char *what;
         Iterator i;
@@ -1799,11 +1817,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
         r = mount_load_proc_self_mountinfo(m, true);
         if (r < 0) {
                 /* Reset flags, just in case, for later calls */
-                LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
-                        Mount *mount = MOUNT(u);
-
-                        mount->is_mounted = mount->just_mounted = mount->just_changed = false;
-                }
+                LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT])
+                        MOUNT(u)->proc_flags = 0;
 
                 return 0;
         }
@@ -1824,7 +1839,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
 
                                 /* Remember that this device might just have disappeared */
                                 if (set_ensure_allocated(&gone, &path_hash_ops) < 0 ||
-                                    set_put(gone, mount->parameters_proc_self_mountinfo.what) < 0)
+                                    set_put_strdup(gone, mount->parameters_proc_self_mountinfo.what) < 0)
                                         log_oom(); /* we don't care too much about OOM here... */
                         }
 
@@ -1833,10 +1848,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                         switch (mount->state) {
 
                         case MOUNT_MOUNTED:
-                                /* This has just been unmounted by
-                                 * somebody else, follow the state
-                                 * change. */
-                                mount->result = MOUNT_SUCCESS; /* make sure we forget any earlier umount failures */
+                                /* This has just been unmounted by somebody else, follow the state change. */
                                 mount_enter_dead(mount, MOUNT_SUCCESS);
                                 break;
 
@@ -1844,7 +1856,7 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                                 break;
                         }
 
-                } else if (mount->just_mounted || mount->just_changed) {
+                } else if (mount->proc_flags & (MOUNT_PROC_JUST_MOUNTED|MOUNT_PROC_JUST_CHANGED)) {
 
                         /* A mount point was added or changed */
 
@@ -1855,7 +1867,8 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
 
                                 /* This has just been mounted by somebody else, follow the state change, but let's
                                  * generate a new invocation ID for this implicitly and automatically. */
-                                (void) unit_acquire_invocation_id(UNIT(mount));
+                                (void) unit_acquire_invocation_id(u);
+                                mount_cycle_clear(mount);
                                 mount_enter_mounted(mount, MOUNT_SUCCESS);
                                 break;
 
@@ -1877,14 +1890,15 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                 if (mount_is_mounted(mount) &&
                     mount->from_proc_self_mountinfo &&
                     mount->parameters_proc_self_mountinfo.what) {
+                        /* Track devices currently used */
 
                         if (set_ensure_allocated(&around, &path_hash_ops) < 0 ||
-                            set_put(around, mount->parameters_proc_self_mountinfo.what) < 0)
+                            set_put_strdup(around, mount->parameters_proc_self_mountinfo.what) < 0)
                                 log_oom();
                 }
 
                 /* Reset the flags for later calls */
-                mount->is_mounted = mount->just_mounted = mount->just_changed = false;
+                mount->proc_flags = 0;
         }
 
         SET_FOREACH(what, gone, i) {
index 67ab8ecf93a3ddeb1eb9c6c03bc85ece8e4a1efe..2e59f1fe04dd28f04c3146d7ba08de3b8db6f359 100644 (file)
@@ -34,6 +34,13 @@ typedef struct MountParameters {
         char *fstype;
 } MountParameters;
 
+/* Used while looking for mount points that vanished or got added from/to /proc/self/mountinfo */
+typedef enum MountProcFlags {
+        MOUNT_PROC_IS_MOUNTED   = 1 << 0,
+        MOUNT_PROC_JUST_MOUNTED = 1 << 1,
+        MOUNT_PROC_JUST_CHANGED = 1 << 2,
+} MountProcFlags;
+
 struct Mount {
         Unit meta;
 
@@ -45,11 +52,7 @@ struct Mount {
         bool from_proc_self_mountinfo:1;
         bool from_fragment:1;
 
-        /* Used while looking for mount points that vanished or got
-         * added from/to /proc/self/mountinfo */
-        bool is_mounted:1;
-        bool just_mounted:1;
-        bool just_changed:1;
+        MountProcFlags proc_flags;
 
         bool sloppy_options;
 
index 01019b0cf77f9e7027ab4d4e9ba87baa45598ed9..831e49df29f2623b0f9e0a49ffaeae66fcf198a8 100644 (file)
@@ -8,6 +8,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "dbus-path.h"
+#include "dbus-unit.h"
 #include "fd-util.h"
 #include "fs-util.h"
 #include "glob-util.h"
@@ -410,6 +411,9 @@ static void path_set_state(Path *p, PathState state) {
         PathState old_state;
         assert(p);
 
+        if (p->state != state)
+                bus_unit_send_pending_change_signal(UNIT(p), false);
+
         old_state = p->state;
         p->state = state;
 
index 151b8989a6416bb38bd7aada60a2ffdb6874636c..e478661f9486fb52849da49f4ebe745b27e3ce16 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "alloc-util.h"
 #include "dbus-scope.h"
+#include "dbus-unit.h"
 #include "load-dropin.h"
 #include "log.h"
 #include "scope.h"
@@ -82,6 +83,9 @@ static void scope_set_state(Scope *s, ScopeState state) {
         ScopeState old_state;
         assert(s);
 
+        if (s->state != state)
+                bus_unit_send_pending_change_signal(UNIT(s), false);
+
         old_state = s->state;
         s->state = state;
 
index 964a7fd05725d62e057c5c4a1e292d9bb5992be1..76f1e160697f7d22f53c4554c9d4645f67368505 100644 (file)
@@ -12,6 +12,7 @@
 #include "bus-kernel.h"
 #include "bus-util.h"
 #include "dbus-service.h"
+#include "dbus-unit.h"
 #include "def.h"
 #include "env-util.h"
 #include "escape.h"
@@ -1035,6 +1036,9 @@ static void service_set_state(Service *s, ServiceState state) {
 
         assert(s);
 
+        if (s->state != state)
+                bus_unit_send_pending_change_signal(UNIT(s), false);
+
         table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
 
         old_state = s->state;
index eae7295acb20a3f63efaef1a31ae2ee5597d599f..cb47ee8984b20322429ed25c51b98d6cdaa84bc5 100644 (file)
@@ -28,6 +28,7 @@
 #include "parse-util.h"
 #include "process-util.h"
 #include "reboot-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "string-util.h"
 #include "switch-root.h"
@@ -443,13 +444,15 @@ int main(int argc, char *argv[]) {
         arguments[2] = NULL;
         execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
 
+        (void) rlimit_nofile_safe();
+
         if (can_initrd) {
                 r = switch_root_initramfs();
                 if (r >= 0) {
                         argv[0] = (char*) "/shutdown";
 
-                        setsid();
-                        make_console_stdio();
+                        (void) setsid();
+                        (void) make_console_stdio();
 
                         log_info("Successfully changed into root pivot.\n"
                                  "Returning to initrd...");
index dc087680e1931dcc74feb701c9b55d7bd9b05e93..15b18bcad3562fb9876a80db1a452e73a1eca0ff 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "alloc-util.h"
 #include "dbus-slice.h"
+#include "dbus-unit.h"
 #include "log.h"
 #include "serialize.h"
 #include "slice.h"
@@ -29,6 +30,9 @@ static void slice_set_state(Slice *t, SliceState state) {
         SliceState old_state;
         assert(t);
 
+        if (t->state != state)
+                bus_unit_send_pending_change_signal(UNIT(t), false);
+
         old_state = t->state;
         t->state = state;
 
index 6697f05fbfd9daa546afd85b34d83d13ea5fb522..dd126a7f21b7d06fe27f2ea3c9fde6452c63ef17 100644 (file)
@@ -17,6 +17,7 @@
 #include "bus-util.h"
 #include "copy.h"
 #include "dbus-socket.h"
+#include "dbus-unit.h"
 #include "def.h"
 #include "exit-status.h"
 #include "fd-util.h"
@@ -1742,6 +1743,9 @@ static void socket_set_state(Socket *s, SocketState state) {
         SocketState old_state;
         assert(s);
 
+        if (s->state != state)
+                bus_unit_send_pending_change_signal(UNIT(s), false);
+
         old_state = s->state;
         s->state = state;
 
index db806fe0bb3bc8a2928f7bf1872ab8ce35273adb..2d8463b8b1812173ec019b0274eaf4d39799cff0 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "alloc-util.h"
 #include "dbus-swap.h"
+#include "dbus-unit.h"
 #include "device-private.h"
 #include "device-util.h"
 #include "device.h"
@@ -272,77 +273,92 @@ static int swap_load_devnode(Swap *s) {
         return swap_set_devnode(s, p);
 }
 
-static int swap_load(Unit *u) {
+static int swap_add_extras(Swap *s) {
         int r;
-        Swap *s = SWAP(u);
 
         assert(s);
-        assert(u->load_state == UNIT_STUB);
 
-        /* Load a .swap file */
-        if (SWAP(u)->from_proc_swaps)
-                r = unit_load_fragment_and_dropin_optional(u);
-        else
-                r = unit_load_fragment_and_dropin(u);
+        if (UNIT(s)->fragment_path)
+                s->from_fragment = true;
+
+        if (!s->what) {
+                if (s->parameters_fragment.what)
+                        s->what = strdup(s->parameters_fragment.what);
+                else if (s->parameters_proc_swaps.what)
+                        s->what = strdup(s->parameters_proc_swaps.what);
+                else {
+                        r = unit_name_to_path(UNIT(s)->id, &s->what);
+                        if (r < 0)
+                                return r;
+                }
+
+                if (!s->what)
+                        return -ENOMEM;
+        }
+
+        path_simplify(s->what, false);
+
+        if (!UNIT(s)->description) {
+                r = unit_set_description(UNIT(s), s->what);
+                if (r < 0)
+                        return r;
+        }
+
+        r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
         if (r < 0)
                 return r;
 
-        if (u->load_state == UNIT_LOADED) {
-
-                if (UNIT(s)->fragment_path)
-                        s->from_fragment = true;
+        r = swap_add_device_dependencies(s);
+        if (r < 0)
+                return r;
 
-                if (!s->what) {
-                        if (s->parameters_fragment.what)
-                                s->what = strdup(s->parameters_fragment.what);
-                        else if (s->parameters_proc_swaps.what)
-                                s->what = strdup(s->parameters_proc_swaps.what);
-                        else {
-                                r = unit_name_to_path(u->id, &s->what);
-                                if (r < 0)
-                                        return r;
-                        }
+        r = swap_load_devnode(s);
+        if (r < 0)
+                return r;
 
-                        if (!s->what)
-                                return -ENOMEM;
-                }
+        r = unit_patch_contexts(UNIT(s));
+        if (r < 0)
+                return r;
 
-                path_simplify(s->what, false);
+        r = unit_add_exec_dependencies(UNIT(s), &s->exec_context);
+        if (r < 0)
+                return r;
 
-                if (!UNIT(s)->description) {
-                        r = unit_set_description(u, s->what);
-                        if (r < 0)
-                                return r;
-                }
+        r = unit_set_default_slice(UNIT(s));
+        if (r < 0)
+                return r;
 
-                r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT);
-                if (r < 0)
-                        return r;
+        r = swap_add_default_dependencies(s);
+        if (r < 0)
+                return r;
 
-                r = swap_add_device_dependencies(s);
-                if (r < 0)
-                        return r;
+        return 0;
+}
 
-                r = swap_load_devnode(s);
-                if (r < 0)
-                        return r;
+static int swap_load(Unit *u) {
+        Swap *s = SWAP(u);
+        int r, q;
 
-                r = unit_patch_contexts(u);
-                if (r < 0)
-                        return r;
+        assert(s);
+        assert(u->load_state == UNIT_STUB);
 
-                r = unit_add_exec_dependencies(u, &s->exec_context);
-                if (r < 0)
-                        return r;
+        /* Load a .swap file */
+        if (SWAP(u)->from_proc_swaps)
+                r = unit_load_fragment_and_dropin_optional(u);
+        else
+                r = unit_load_fragment_and_dropin(u);
 
-                r = unit_set_default_slice(u);
-                if (r < 0)
-                        return r;
+        /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is already
+         * active. */
+        if (u->load_state == UNIT_LOADED || s->from_proc_swaps)
+                q = swap_add_extras(s);
+        else
+                q = 0;
 
-                r = swap_add_default_dependencies(s);
-                if (r < 0)
-                        return r;
-        }
+        if (r < 0)
+                return r;
+        if (q < 0)
+                return q;
 
         return swap_verify(s);
 }
@@ -369,7 +385,6 @@ static int swap_setup_unit(
                 return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m");
 
         u = manager_get_unit(m, e);
-
         if (u &&
             SWAP(u)->from_proc_swaps &&
             !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps))
@@ -404,6 +419,13 @@ static int swap_setup_unit(
                 }
         }
 
+        /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be
+         * loaded. After all we can load it now, from the data in /proc/swaps. */
+        if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) {
+                u->load_state = UNIT_LOADED;
+                u->load_error = 0;
+        }
+
         if (set_flags) {
                 SWAP(u)->is_active = true;
                 SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps;
@@ -471,7 +493,7 @@ static int swap_process_new(Manager *m, const char *device, int prio, bool set_f
                 swap_setup_unit(m, devlink, device, prio, set_flags);
         }
 
-        return r;
+        return 0;
 }
 
 static void swap_set_state(Swap *s, SwapState state) {
@@ -480,6 +502,9 @@ static void swap_set_state(Swap *s, SwapState state) {
 
         assert(s);
 
+        if (s->state != state)
+                bus_unit_send_pending_change_signal(UNIT(s), false);
+
         old_state = s->state;
         s->state = state;
 
@@ -809,6 +834,14 @@ fail:
         swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
 }
 
+static void swap_cycle_clear(Swap *s) {
+        assert(s);
+
+        s->result = SWAP_SUCCESS;
+        exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
+        UNIT(s)->reset_accounting = true;
+}
+
 static int swap_start(Unit *u) {
         Swap *s = SWAP(u), *other;
         int r;
@@ -848,11 +881,7 @@ static int swap_start(Unit *u) {
         if (r < 0)
                 return r;
 
-        s->result = SWAP_SUCCESS;
-        exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
-
-        u->reset_accounting = true;
-
+        swap_cycle_clear(s);
         swap_enter_activating(s);
         return 1;
 }
@@ -1084,7 +1113,6 @@ static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userd
 
 static int swap_load_proc_swaps(Manager *m, bool set_flags) {
         unsigned i;
-        int r = 0;
 
         assert(m);
 
@@ -1116,12 +1144,10 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
 
                 device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP);
 
-                k = swap_process_new(m, d, prio, set_flags);
-                if (k < 0)
-                        r = k;
+                (void) swap_process_new(m, d, prio, set_flags);
         }
 
-        return r;
+        return 0;
 }
 
 static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
@@ -1152,13 +1178,13 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
                 Swap *swap = SWAP(u);
 
                 if (!swap->is_active) {
-                        /* This has just been deactivated */
 
                         swap_unset_proc_swaps(swap);
 
                         switch (swap->state) {
 
                         case SWAP_ACTIVE:
+                                /* This has just been deactivated */
                                 swap_enter_dead(swap, SWAP_SUCCESS);
                                 break;
 
@@ -1179,7 +1205,8 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
 
                         case SWAP_DEAD:
                         case SWAP_FAILED:
-                                (void) unit_acquire_invocation_id(UNIT(swap));
+                                (void) unit_acquire_invocation_id(u);
+                                swap_cycle_clear(swap);
                                 swap_enter_active(swap, SWAP_SUCCESS);
                                 break;
 
index b8b8e32805eb0988b4a90150457c93dc2063abe6..421a304c73da421b14a962ab2cb35e962e23a248 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "dbus-target.h"
+#include "dbus-unit.h"
 #include "log.h"
 #include "serialize.h"
 #include "special.h"
@@ -18,6 +19,9 @@ static void target_set_state(Target *t, TargetState state) {
         TargetState old_state;
         assert(t);
 
+        if (t->state != state)
+                bus_unit_send_pending_change_signal(UNIT(t), false);
+
         old_state = t->state;
         t->state = state;
 
index 1527aab158279b9ce18c9e04658e261e09df15b2..d9ba2f76b3d3984d6745824ee74cc4abdea9185c 100644 (file)
@@ -6,6 +6,7 @@
 #include "bus-error.h"
 #include "bus-util.h"
 #include "dbus-timer.h"
+#include "dbus-unit.h"
 #include "fs-util.h"
 #include "parse-util.h"
 #include "random-util.h"
@@ -247,6 +248,9 @@ static void timer_set_state(Timer *t, TimerState state) {
         TimerState old_state;
         assert(t);
 
+        if (t->state != state)
+                bus_unit_send_pending_change_signal(UNIT(t), false);
+
         old_state = t->state;
         t->state = state;
 
index 122b399d66805c4123268a83ca4918dd0f1ef75b..e1b6e9f11cc67a8f0ecc84672d575a811709caae 100644 (file)
@@ -1639,6 +1639,8 @@ static bool unit_condition_test(Unit *u) {
         dual_timestamp_get(&u->condition_timestamp);
         u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string);
 
+        unit_add_to_dbus_queue(u);
+
         return u->condition_result;
 }
 
@@ -1648,6 +1650,8 @@ static bool unit_assert_test(Unit *u) {
         dual_timestamp_get(&u->assert_timestamp);
         u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string);
 
+        unit_add_to_dbus_queue(u);
+
         return u->assert_result;
 }
 
@@ -2339,6 +2343,10 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
 
         m = u->manager;
 
+        /* Let's enqueue the change signal early. In case this unit has a job associated we want that this unit is in
+         * the bus queue, so that any job change signal queued will force out the unit change signal first. */
+        unit_add_to_dbus_queue(u);
+
         /* Update timestamps for state changes */
         if (!MANAGER_IS_RELOADING(m)) {
                 dual_timestamp_get(&u->state_change_timestamp);
@@ -2497,7 +2505,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
                 }
         }
 
-        unit_add_to_dbus_queue(u);
         unit_add_to_gc_queue(u);
 }
 
@@ -4930,7 +4937,7 @@ void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) {
 
         r = unit_ref_uid_gid(u, uid, gid);
         if (r > 0)
-                bus_unit_send_change_signal(u);
+                unit_add_to_dbus_queue(u);
 }
 
 int unit_set_invocation_id(Unit *u, sd_id128_t id) {
@@ -4984,6 +4991,7 @@ int unit_acquire_invocation_id(Unit *u) {
         if (r < 0)
                 return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m");
 
+        unit_add_to_dbus_queue(u);
         return 0;
 }
 
index 8fbe653f0cc9e49d6b848473183fff0a72c71e97..fbee242962feb699c8360cf09edde25c16e2030e 100644 (file)
@@ -968,7 +968,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
 
         fork_name = strjoina("(", arg_debugger, ")");
 
-        r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+        r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 goto finish;
         if (r == 0) {
index 328f5654e88be779b40aa5b68986747d4108799d..379226641e5c31065944109eade7b89f2744bcef 100644 (file)
@@ -169,7 +169,7 @@ static int found_override(const char *top, const char *bottom) {
 
         fflush(stdout);
 
-        r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+        r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index 995cf92ef121cbd3ddfcfd75d1af26e68abf97a7..7fc4a283ce838ff762a1a7f91ef82261739a06e3 100644 (file)
@@ -27,6 +27,7 @@
 #include "path-util.h"
 #include "proc-cmdline.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "socket-util.h"
 #include "special.h"
@@ -401,6 +402,8 @@ static int run(int argc, char *argv[]) {
                 cmdline[i++] = device;
                 cmdline[i++] = NULL;
 
+                (void) rlimit_nofile_safe();
+
                 execv(cmdline[0], (char**) cmdline);
                 _exit(FSCK_OPERATIONAL_ERROR);
         }
index 389b545ac27ce14801d07727e5b8e394f0153bb3..3a1e60fc5dd4db82f286a94449c4ff45ea8eb8ed 100644 (file)
@@ -1,7 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/icmp6.h>
 #include <arpa/inet.h>
+#include <netinet/icmp6.h>
+#include <unistd.h>
 
 #include "alloc-util.h"
 #include "icmp6-util.h"
index a90693c802b83be1a936e557ea596e28897dc577..acfe3809695dc9324f42fc95ee469349d90f91ec 100644 (file)
@@ -14,6 +14,7 @@
 #include "process-util.h"
 #include "pull-common.h"
 #include "pull-job.h"
+#include "rlimit-util.h"
 #include "rm-rf.h"
 #include "signal-util.h"
 #include "siphash24.h"
@@ -472,6 +473,8 @@ int pull_verify(PullJob *main_job,
                         _exit(EXIT_FAILURE);
                 }
 
+                (void) rlimit_nofile_safe();
+
                 cmd[k++] = strjoina("--homedir=", gpg_home);
 
                 /* We add the user keyring only to the command line
index 69bc447920ec21c1c67c1faa9e743c9133467f4a..4185af63e1908d29a73009d5a8db203b11cf8358 100644 (file)
@@ -18,6 +18,7 @@
 #include "hostname-util.h"
 #include "log.h"
 #include "logs-show.h"
+#include "main-func.h"
 #include "microhttpd-util.h"
 #include "os-util.h"
 #include "parse-util.h"
 static char *arg_key_pem = NULL;
 static char *arg_cert_pem = NULL;
 static char *arg_trust_pem = NULL;
-static char *arg_directory = NULL;
+static const char *arg_directory = NULL;
+
+STATIC_DESTRUCTOR_REGISTER(arg_key_pem, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_trust_pem, freep);
 
 typedef struct RequestMeta {
         sd_journal *journal;
@@ -981,95 +986,85 @@ static int parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-int main(int argc, char *argv[]) {
-        struct MHD_Daemon *d = NULL;
+static int run(int argc, char *argv[]) {
+        _cleanup_(MHD_stop_daemonp) struct MHD_Daemon *d = NULL;
+        struct MHD_OptionItem opts[] = {
+                { MHD_OPTION_NOTIFY_COMPLETED,
+                  (intptr_t) request_meta_free, NULL },
+                { MHD_OPTION_EXTERNAL_LOGGER,
+                  (intptr_t) microhttpd_logger, NULL },
+                { MHD_OPTION_END, 0, NULL },
+                { MHD_OPTION_END, 0, NULL },
+                { MHD_OPTION_END, 0, NULL },
+                { MHD_OPTION_END, 0, NULL },
+                { MHD_OPTION_END, 0, NULL },
+        };
+        int opts_pos = 2;
+
+        /* We force MHD_USE_ITC here, in order to make sure
+         * libmicrohttpd doesn't use shutdown() on our listening
+         * socket, which would break socket re-activation. See
+         *
+         * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html
+         * https://github.com/systemd/systemd/pull/1286
+         */
+
+        int flags =
+                MHD_USE_DEBUG |
+                MHD_USE_DUAL_STACK |
+                MHD_USE_ITC |
+                MHD_USE_POLL_INTERNAL_THREAD |
+                MHD_USE_THREAD_PER_CONNECTION;
         int r, n;
 
         log_setup_service();
 
         r = parse_argv(argc, argv);
-        if (r < 0)
-                return EXIT_FAILURE;
-        if (r == 0)
-                return EXIT_SUCCESS;
+        if (r <= 0)
+                return r;
 
         sigbus_install();
 
         r = setup_gnutls_logger(NULL);
         if (r < 0)
-                return EXIT_FAILURE;
+                return r;
 
         n = sd_listen_fds(1);
-        if (n < 0) {
-                log_error_errno(n, "Failed to determine passed sockets: %m");
-                goto finish;
-        } else if (n > 1) {
-                log_error("Can't listen on more than one socket.");
-                goto finish;
-        } else {
-                struct MHD_OptionItem opts[] = {
-                        { MHD_OPTION_NOTIFY_COMPLETED,
-                          (intptr_t) request_meta_free, NULL },
-                        { MHD_OPTION_EXTERNAL_LOGGER,
-                          (intptr_t) microhttpd_logger, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL },
-                        { MHD_OPTION_END, 0, NULL }};
-                int opts_pos = 2;
-
-                /* We force MHD_USE_ITC here, in order to make sure
-                 * libmicrohttpd doesn't use shutdown() on our listening
-                 * socket, which would break socket re-activation. See
-                 *
-                 * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html
-                 * https://github.com/systemd/systemd/pull/1286
-                 */
-
-                int flags =
-                        MHD_USE_DEBUG |
-                        MHD_USE_DUAL_STACK |
-                        MHD_USE_ITC |
-                        MHD_USE_POLL_INTERNAL_THREAD |
-                        MHD_USE_THREAD_PER_CONNECTION;
-
-                if (n > 0)
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START};
-                if (arg_key_pem) {
-                        assert(arg_cert_pem);
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem};
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem};
-                        flags |= MHD_USE_TLS;
-                }
-                if (arg_trust_pem) {
-                        assert(flags & MHD_USE_TLS);
-                        opts[opts_pos++] = (struct MHD_OptionItem)
-                                {MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem};
-                }
-
-                d = MHD_start_daemon(flags, 19531,
-                                     NULL, NULL,
-                                     request_handler, NULL,
-                                     MHD_OPTION_ARRAY, opts,
-                                     MHD_OPTION_END);
+        if (n < 0)
+                return log_error_errno(n, "Failed to determine passed sockets: %m");
+        if (n > 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't listen on more than one socket.");
+
+        if (n == 1)
+                opts[opts_pos++] = (struct MHD_OptionItem)
+                        { MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START };
+
+        if (arg_key_pem) {
+                assert(arg_cert_pem);
+                opts[opts_pos++] = (struct MHD_OptionItem)
+                        { MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem };
+                opts[opts_pos++] = (struct MHD_OptionItem)
+                        { MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem };
+                flags |= MHD_USE_TLS;
         }
 
-        if (!d) {
-                log_error("Failed to start daemon!");
-                goto finish;
+        if (arg_trust_pem) {
+                assert(flags & MHD_USE_TLS);
+                opts[opts_pos++] = (struct MHD_OptionItem)
+                        { MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem };
         }
 
-        pause();
-
-        r = EXIT_SUCCESS;
+        d = MHD_start_daemon(flags, 19531,
+                             NULL, NULL,
+                             request_handler, NULL,
+                             MHD_OPTION_ARRAY, opts,
+                             MHD_OPTION_END);
+        if (!d)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start daemon!");
 
-finish:
-        if (d)
-                MHD_stop_daemon(d);
+        pause();
 
-        return r;
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index c46e0acdd369354d4a20ec64484b1d4e6d2e2614..e1748cb46b8425feb9b12479f5daecfa7b0f1f28 100644 (file)
@@ -6,11 +6,13 @@
 #include "sd-daemon.h"
 
 #include "conf-parser.h"
+#include "daemon-util.h"
 #include "def.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "journal-remote-write.h"
 #include "journal-remote.h"
+#include "main-func.h"
 #include "pretty-print.h"
 #include "process-util.h"
 #include "rlimit-util.h"
 #define CERT_FILE     CERTIFICATE_ROOT "/certs/journal-remote.pem"
 #define TRUST_FILE    CERTIFICATE_ROOT "/ca/trusted.pem"
 
-static char* arg_url = NULL;
-static char* arg_getter = NULL;
-static char* arg_listen_raw = NULL;
-static char* arg_listen_http = NULL;
-static char* arg_listen_https = NULL;
-static char** arg_files = NULL;
+static const char* arg_url = NULL;
+static const char* arg_getter = NULL;
+static const char* arg_listen_raw = NULL;
+static const char* arg_listen_http = NULL;
+static const char* arg_listen_https = NULL;
+static char** arg_files = NULL; /* Do not free this. */
 static int arg_compress = true;
 static int arg_seal = false;
 static int http_socket = -1, https_socket = -1;
 static char** arg_gnutls_log = NULL;
 
 static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID;
-static char* arg_output = NULL;
+static const char* arg_output = NULL;
 
 static char *arg_key = NULL;
 static char *arg_cert = NULL;
 static char *arg_trust = NULL;
 static bool arg_trust_all = false;
 
+STATIC_DESTRUCTOR_REGISTER(arg_gnutls_log, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_key, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_cert, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_trust, freep);
+
 static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = {
         [JOURNAL_WRITE_SPLIT_NONE] = "none",
         [JOURNAL_WRITE_SPLIT_HOST] = "host",
@@ -81,6 +88,8 @@ static int spawn_child(const char* child, char** argv) {
                         _exit(EXIT_FAILURE);
                 }
 
+                (void) rlimit_nofile_safe();
+
                 execvp(child, argv);
                 log_error_errno(errno, "Failed to exec child %s: %m", child);
                 _exit(EXIT_FAILURE);
@@ -613,8 +622,7 @@ static int create_remoteserver(
         }
 
         if (arg_url) {
-                const char *url;
-                char *hostname;
+                const char *url, *hostname;
 
                 if (!strstr(arg_url, "/entries")) {
                         if (endswith(arg_url, "/"))
@@ -635,7 +643,7 @@ static int create_remoteserver(
 
                 hostname = strndupa(hostname, strcspn(hostname, "/:"));
 
-                r = journal_remote_add_source(s, fd, hostname, false);
+                r = journal_remote_add_source(s, fd, (char *) hostname, false);
                 if (r < 0)
                         return r;
         }
@@ -1059,10 +1067,11 @@ static int load_certificates(char **key, char **cert, char **trust) {
         return 0;
 }
 
-int main(int argc, char **argv) {
-        RemoteServer s = {};
-        int r;
+static int run(int argc, char **argv) {
+        _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+        _cleanup_(journal_remote_server_destroy) RemoteServer s = {};
         _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
+        int r;
 
         log_show_color(true);
         log_parse_environment();
@@ -1072,63 +1081,61 @@ int main(int argc, char **argv) {
 
         r = parse_config();
         if (r < 0)
-                return EXIT_FAILURE;
+                return r;
 
         r = parse_argv(argc, argv);
         if (r <= 0)
-                return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+                return r;
 
         if (arg_listen_http || arg_listen_https) {
                 r = setup_gnutls_logger(arg_gnutls_log);
                 if (r < 0)
-                        return EXIT_FAILURE;
+                        return r;
         }
 
         if (arg_listen_https || https_socket >= 0) {
-                if (load_certificates(&key, &cert, &trust) < 0)
-                        return EXIT_FAILURE;
+                r = load_certificates(&key, &cert, &trust);
+                if (r < 0)
+                        return r;
+
                 s.check_trust = !arg_trust_all;
         }
 
-        if (create_remoteserver(&s, key, cert, trust) < 0)
-                return EXIT_FAILURE;
+        r = create_remoteserver(&s, key, cert, trust);
+        if (r < 0)
+                return r;
 
         r = sd_event_set_watchdog(s.events, true);
         if (r < 0)
-                log_error_errno(r, "Failed to enable watchdog: %m");
-        else
-                log_debug("Watchdog is %sd.", enable_disable(r > 0));
+                return log_error_errno(r, "Failed to enable watchdog: %m");
+
+        log_debug("Watchdog is %sd.", enable_disable(r > 0));
 
         log_debug("%s running as pid "PID_FMT,
                   program_invocation_short_name, getpid_cached());
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing requests...");
+
+        notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
 
         while (s.active) {
                 r = sd_event_get_state(s.events);
                 if (r < 0)
-                        break;
+                        return r;
                 if (r == SD_EVENT_FINISHED)
                         break;
 
                 r = sd_event_run(s.events, -1);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to run event loop: %m");
-                        break;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to run event loop: %m");
         }
 
-        sd_notifyf(false,
-                   "STOPPING=1\n"
-                   "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
-        log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
-
-        journal_remote_server_destroy(&s);
+        notify_message = NULL;
+        (void) sd_notifyf(false,
+                          "STOPPING=1\n"
+                          "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count);
 
-        free(arg_key);
-        free(arg_cert);
-        free(arg_trust);
+        log_info("Finishing after writing %" PRIu64 " entries", s.event_count);
 
-        return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 1f3cdb932f7593c292817d4134c6751b7ef48380..3c0916c4383236611dc037d77e1f98fa2f865f60 100644 (file)
@@ -346,7 +346,7 @@ static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) {
 }
 #endif
 
-RemoteServer* journal_remote_server_destroy(RemoteServer *s) {
+void journal_remote_server_destroy(RemoteServer *s) {
         size_t i;
 
 #if HAVE_MICROHTTPD
@@ -370,7 +370,6 @@ RemoteServer* journal_remote_server_destroy(RemoteServer *s) {
                 journal_remote_server_global = NULL;
 
         /* fds that we're listening on remain open... */
-        return NULL;
 }
 
 /**********************************************************************
index e083ea9c74975a208cefad4fd9881f1218463534..4c25d43abf955a6d352fda60aca0d3836dcb6f01 100644 (file)
@@ -62,4 +62,4 @@ int journal_remote_handle_raw_source(
                 uint32_t revents,
                 RemoteServer *s);
 
-RemoteServer* journal_remote_server_destroy(RemoteServer *s);
+void journal_remote_server_destroy(RemoteServer *s);
index 7f08809c54416e6a344f34506c61496fcd6440cd..1e08fcc55415468597086855c8a8bd5e2705d6fd 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "alloc-util.h"
 #include "conf-parser.h"
+#include "daemon-util.h"
 #include "def.h"
 #include "env-file.h"
 #include "fd-util.h"
@@ -18,6 +19,7 @@
 #include "glob-util.h"
 #include "journal-upload.h"
 #include "log.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "parse-util.h"
 #include "pretty-print.h"
@@ -761,10 +763,11 @@ static int open_journal(sd_journal **j) {
         return r;
 }
 
-int main(int argc, char **argv) {
-        Uploader u;
-        int r;
+static int run(int argc, char **argv) {
+        _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
+        _cleanup_(destroy_uploader) Uploader u = {};
         bool use_journal;
+        int r;
 
         log_show_color(true);
         log_parse_environment();
@@ -774,23 +777,23 @@ int main(int argc, char **argv) {
 
         r = parse_config();
         if (r < 0)
-                goto finish;
+                return r;
 
         r = parse_argv(argc, argv);
         if (r <= 0)
-                goto finish;
+                return r;
 
         sigbus_install();
 
         r = setup_uploader(&u, arg_url, arg_save_state);
         if (r < 0)
-                goto cleanup;
+                return r;
 
         sd_event_set_watchdog(u.events, true);
 
         r = check_cursor_updating(&u);
         if (r < 0)
-                goto cleanup;
+                return r;
 
         log_debug("%s running as pid "PID_FMT,
                   program_invocation_short_name, getpid_cached());
@@ -800,61 +803,51 @@ int main(int argc, char **argv) {
                 sd_journal *j;
                 r = open_journal(&j);
                 if (r < 0)
-                        goto finish;
+                        return r;
                 r = open_journal_for_upload(&u, j,
                                             arg_cursor ?: u.last_cursor,
                                             arg_cursor ? arg_after_cursor : true,
                                             !!arg_follow);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
 
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing input...");
+        notify_message = notify_start("READY=1\n"
+                                      "STATUS=Processing input...",
+                                      NOTIFY_STOPPING);
 
         for (;;) {
                 r = sd_event_get_state(u.events);
                 if (r < 0)
-                        break;
+                        return r;
                 if (r == SD_EVENT_FINISHED)
-                        break;
+                        return 0;
 
                 if (use_journal) {
                         if (!u.journal)
-                                break;
+                                return 0;
 
                         r = check_journal_input(&u);
                 } else if (u.input < 0 && !use_journal) {
                         if (optind >= argc)
-                                break;
+                                return 0;
 
                         log_debug("Using %s as input.", argv[optind]);
                         r = open_file_for_upload(&u, argv[optind++]);
                 }
                 if (r < 0)
-                        goto cleanup;
+                        return r;
 
                 if (u.uploading) {
                         r = perform_upload(&u);
                         if (r < 0)
-                                break;
+                                return r;
                 }
 
                 r = sd_event_run(u.events, u.timeout);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to run event loop: %m");
-                        break;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Failed to run event loop: %m");
         }
-
-cleanup:
-        sd_notify(false,
-                  "STOPPING=1\n"
-                  "STATUS=Shutting down...");
-
-        destroy_uploader(&u);
-
-finish:
-        return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index a50a2a75c7fc30ef56f790f7de60306516d7a7c2..364cd0f7cfd2c339e7b9475d96ac8bcc2cf29ed1 100644 (file)
@@ -73,3 +73,5 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
  * interesting events without overwhelming detail.
  */
 int setup_gnutls_logger(char **categories);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
index b30963da667b397467d9f9b58488645f66e5f05f..7b3dc1e9ab0eed9ddf0512c6132a096497f8b01a 100644 (file)
@@ -1,12 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <stdio.h>
-#include <linux/audit.h>
-#if HAVE_AUDIT
-#  include <libaudit.h>
-#endif
-
-#include "missing.h"
 #include "audit-type.h"
+#include "missing_audit.h"
+
 #include "audit_type-to-name.h"
-#include "macro.h"
index 965b044cbf0d3221bdc521c497a17e6cb7460f43..069a883490d69b0b071d3327996bd2caa1a82db9 100644 (file)
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <alloca.h>
+#include <stdio.h>
+
 #include "macro.h"
 
 const char *audit_type_to_string(int type);
index 807dece545c96dffcab9186674741d39be40aea4..e03d6dc232713a35da9e60216e46d9514149f417 100644 (file)
@@ -34,7 +34,7 @@ endif
 ############################################################
 
 audit_type_includes = [config_h,
-                       missing_h,
+                       missing_audit_h,
                        'linux/audit.h']
 if conf.get('HAVE_AUDIT') == 1
         audit_type_includes += 'libaudit.h'
index e5cd134d57f74d3149e697c57f3d7dd8d883afa2..969fc71051bcead68d4eed3096e30381fa9a6869 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <arpa/inet.h>
 #include <linux/sockios.h>
+#include <sys/ioctl.h>
 
 #include "sd-lldp.h"
 
index d88b018dc9432d073e22ca397875f7bb89e31469..fa94b3cb7529bb632aaa1947e1cf35e63a90069f 100644 (file)
@@ -20,6 +20,7 @@
 #include "macro.h"
 #include "socket-util.h"
 #include "tests.h"
+#include "util.h"
 #include "virt.h"
 
 static struct ether_addr mac_addr = {
index 071691327b712e615bac86df8ade0a6384bcf9b0..f441bb6972ea1e86a563d2b4ec64a4474df26bcf 100644 (file)
@@ -8,7 +8,7 @@ id128_sources = files('''
 
 sd_daemon_c = files('sd-daemon/sd-daemon.c')
 
-sd_event_c = files('''
+sd_event_sources = files('''
         sd-event/event-source.h
         sd-event/event-util.c
         sd-event/event-util.h
@@ -90,7 +90,7 @@ libsystemd_sources = files('''
         sd-path/sd-path.c
         sd-resolve/sd-resolve.c
         sd-utf8/sd-utf8.c
-'''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c
+'''.split()) + id128_sources + sd_daemon_c + sd_event_sources + sd_login_c
 
 disable_mempool_c = files('disable-mempool.c')
 
index 2787e8505ba404c5b0d6c0cdffdc73400d121d66..7775d2b376253edae1ffcd061b45e96f989e2018 100644 (file)
@@ -430,7 +430,7 @@ _public_ int sd_bus_get_name_creds(
 
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
-        const char *unique = NULL;
+        const char *unique;
         pid_t pid = 0;
         int r;
 
@@ -459,9 +459,12 @@ _public_ int sd_bus_get_name_creds(
         if (!BUS_IS_OPEN(bus->state))
                 return -ENOTCONN;
 
-        /* Only query the owner if the caller wants to know it or if
-         * the caller just wants to check whether a name exists */
-        if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
+        /* If the name is unique anyway, we can use it directly */
+        unique = name[0] == ':' ? name : NULL;
+
+        /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just
+         * wants to check whether a name exists */
+        if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) {
                 r = sd_bus_call_method(
                                 bus,
                                 "org.freedesktop.DBus",
@@ -483,6 +486,7 @@ _public_ int sd_bus_get_name_creds(
         if (mask != 0) {
                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 bool need_pid, need_uid, need_selinux, need_separate_calls;
+
                 c = bus_creds_new();
                 if (!c)
                         return -ENOMEM;
@@ -661,7 +665,7 @@ _public_ int sd_bus_get_name_creds(
                                                 NULL,
                                                 &reply,
                                                 "s",
-                                                unique ? unique : name);
+                                                unique ?: name);
                                 if (r < 0)
                                         return r;
 
@@ -688,7 +692,7 @@ _public_ int sd_bus_get_name_creds(
                                                 &error,
                                                 &reply,
                                                 "s",
-                                                unique ? unique : name);
+                                                unique ?: name);
                                 if (r < 0) {
                                         if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
                                                 return r;
@@ -699,7 +703,7 @@ _public_ int sd_bus_get_name_creds(
                                         if (r < 0)
                                                 return r;
 
-                                        c->label = strndup(p, sz);
+                                        c->label = memdup_suffix0(p, sz);
                                         if (!c->label)
                                                 return -ENOMEM;
 
index 506ed0d73c3303444258796b490217f7e7c032d6..38900cf718be84051211bd2ab2d37980b3085f17 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <sys/time.h>
+
 #include "alloc-util.h"
 #include "bus-dump.h"
 #include "bus-internal.h"
index 7e90a56e6774689e681f414bdba755e57a225a78..d0538104ae251100f2e1ffd1f366040d646d6bfc 100644 (file)
@@ -9,6 +9,7 @@
 #include "bus-slot.h"
 #include "bus-type.h"
 #include "bus-util.h"
+#include "missing_capability.h"
 #include "set.h"
 #include "string-util.h"
 #include "strv.h"
index f7485211ac60ec15c6eedef4c1dba6246fe75424..ed185131b83ae40215398b0453191cc67b2db2b4 100644 (file)
@@ -21,6 +21,7 @@
 #include "missing.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "selinux-util.h"
 #include "signal-util.h"
 #include "stdio-util.h"
@@ -932,6 +933,8 @@ int bus_socket_exec(sd_bus *b) {
                 if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
                         _exit(EXIT_FAILURE);
 
+                (void) rlimit_nofile_safe();
+
                 if (b->exec_argv)
                         execvp(b->exec_path, b->exec_argv);
                 else {
index 92624909e00132245fe84aab2f25bd8357ee8b0c..2dd3d41a302a290b6c9409e26ce1292909d3ac2d 100644 (file)
@@ -10,6 +10,7 @@
 #include "bus-util.h"
 #include "def.h"
 #include "fd-util.h"
+#include "missing_resource.h"
 #include "time-util.h"
 #include "util.h"
 
index 39def1681eeb22697b83fe19940325f63621fee1..d5583488f20ce828fb430ba20ab77b60b22aecef 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <ctype.h>
 #include <net/if.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 
 #include "sd-device.h"
index 874babc9efdbcc87a787fa807ccab4a4895980a0..64ab386df3f1c0a7378a62254976c79f0a34bc3e 100644 (file)
@@ -412,17 +412,40 @@ static const NLTypeSystem rtnl_link_info_type_system = {
 };
 
 static const struct NLType rtnl_prot_info_bridge_port_types[] = {
-        [IFLA_BRPORT_STATE]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_COST]              = { .type = NETLINK_TYPE_U32 },
-        [IFLA_BRPORT_PRIORITY]          = { .type = NETLINK_TYPE_U16 },
-        [IFLA_BRPORT_MODE]              = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_GUARD]             = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PROTECT]           = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_FAST_LEAVE]        = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_LEARNING]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_UNICAST_FLOOD]     = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_PROXYARP]          = { .type = NETLINK_TYPE_U8 },
-        [IFLA_BRPORT_LEARNING_SYNC]     = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_STATE]               = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_COST]                = { .type = NETLINK_TYPE_U32 },
+        [IFLA_BRPORT_PRIORITY]            = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_MODE]                = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_GUARD]               = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_PROTECT]             = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_FAST_LEAVE]          = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_LEARNING]            = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_UNICAST_FLOOD]       = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_PROXYARP]            = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_LEARNING_SYNC]       = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_PROXYARP_WIFI]       = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_ROOT_ID]             = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_BRIDGE_ID]           = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_DESIGNATED_PORT]     = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_DESIGNATED_COST]     = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_ID]                  = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_NO]                  = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_CONFIG_PENDING]      = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_MESSAGE_AGE_TIMER]   = { .type = NETLINK_TYPE_U64 },
+        [IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 },
+        [IFLA_BRPORT_HOLD_TIMER]          = { .type = NETLINK_TYPE_U64 },
+        [IFLA_BRPORT_FLUSH]               = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_MULTICAST_ROUTER]    = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_PAD]                 = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_MCAST_FLOOD]         = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_MCAST_TO_UCAST]      = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_VLAN_TUNNEL]         = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_BCAST_FLOOD]         = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_GROUP_FWD_MASK]      = { .type = NETLINK_TYPE_U16 },
+        [IFLA_BRPORT_NEIGH_SUPPRESS]      = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_ISOLATED]            = { .type = NETLINK_TYPE_U8 },
+        [IFLA_BRPORT_BACKUP_PORT]         = { .type = NETLINK_TYPE_U32 },
 };
 
 static const NLTypeSystem rtnl_prot_info_type_systems[] = {
index 4416e1720cb2e65a48a464a1aa93f0497130a978..2d4d00e0eb128571b191f0c1629be9685c4ba215 100644 (file)
@@ -852,6 +852,32 @@ int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, unsigne
         return 0;
 }
 
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) {
+        struct rtmsg *routing_policy_rule;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+        routing_policy_rule = NLMSG_DATA(m->hdr);
+        routing_policy_rule->rtm_flags |= flags;
+
+        return 0;
+}
+
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags) {
+        struct rtmsg *routing_policy_rule;
+
+        assert_return(m, -EINVAL);
+        assert_return(m->hdr, -EINVAL);
+        assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
+
+        routing_policy_rule = NLMSG_DATA(m->hdr);
+        *flags = routing_policy_rule->rtm_flags;
+
+        return 0;
+}
+
 int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) {
         struct rtmsg *routing_policy_rule;
 
index 77481002106f673a06583df12d31158beedc3381..bff2c4976b9e5d4b171c60b0ac9a18a20e97cb68 100644 (file)
@@ -14,6 +14,7 @@
 #include "macro.h"
 #include "socket-util.h"
 #include "string-util.h"
+#include "time-util.h"
 
 #define TEST_TIMEOUT_USEC (20*USEC_PER_SEC)
 
index 03bbf3b82604f2ca4491f1f5b1f6df2c0c0046ba..f574d429f49f8d0e1d87d331859dddc5d5391816 100644 (file)
@@ -303,7 +303,7 @@ static int run(int argc, char *argv[]) {
                 if (fd < 0)
                         return log_error_errno(fd, "Failed to inhibit: %s", bus_error_message(&error, fd));
 
-                r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+                r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
                 if (r < 0)
                         return r;
                 if (r == 0) {
index a311ed9077d537ca4ddb590569bda165d34d6a07..7e7f0d51bfb0db5ea8a2adaf82b9d626788a6442 100644 (file)
@@ -15,6 +15,7 @@
 #include "io-util.h"
 #include "loop-util.h"
 #include "machine-image.h"
+#include "missing_capability.h"
 #include "mount-util.h"
 #include "process-util.h"
 #include "raw-clone.h"
@@ -169,7 +170,7 @@ int bus_image_method_clone(
         if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
                 return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
 
-        r = safe_fork("(imgclone)", FORK_RESET_SIGNALS, &child);
+        r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
         if (r < 0)
                 return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
         if (r == 0) {
index 95489a3d9492982a4b444f0334b905bedac19a17..285918b4cc5c63f9badd98718a8371924e953ac9 100644 (file)
@@ -27,6 +27,7 @@
 #include "local-addresses.h"
 #include "machine-dbus.h"
 #include "machine.h"
+#include "missing_capability.h"
 #include "mkdir.h"
 #include "os-util.h"
 #include "path-util.h"
index bbcfc626a1d01a2d9aa129cd2a6ac1287e1fd18e..d613414fded43b55efb3b0b6d842c2a6f1add0e5 100644 (file)
@@ -21,6 +21,7 @@
 #include "machine-image.h"
 #include "machine-pool.h"
 #include "machined.h"
+#include "missing_capability.h"
 #include "path-util.h"
 #include "process-util.h"
 #include "stdio-util.h"
index d4fa27a288ff5a8919b24521b0a666eece26e8a2..8fe4854424b8cd08ff77b4acccf6ba43b185fffb 100644 (file)
@@ -64,6 +64,8 @@ sources = files('''
         networkd-manager.h
         networkd-ndisc.c
         networkd-ndisc.h
+        networkd-neighbor.c
+        networkd-neighbor.h
         networkd-radv.c
         networkd-radv.h
         networkd-network-bus.c
index 9e4c1e962939e6b6f75041cd1c66a456637a8e72..b8abed19bd9160085e4507e11b3d2b6fd0855751 100644 (file)
@@ -6,7 +6,7 @@
 #endif
 
 #include "in-addr-util.h"
-#include "missing.h"
+#include "missing_fou.h"
 #include "netdev/netdev.h"
 
 typedef enum FooOverUDPEncapType {
index b60587f2b6f3c6bf69f7fbd9d3368bda719a721b..fb426d37e5d814a4eedb5b8a4b89d138d514d879 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/if_link.h>
 
-#include "missing.h"
+#include "missing_if_link.h"
 #include "netdev/netdev.h"
 
 typedef enum IPVlanMode {
index 49752c2d8a2e96bcd57dc61573c37b08aee636ae..fbc7a59e9e8ca3749947b14ff0fd8be20d63b232 100644 (file)
@@ -73,6 +73,7 @@ Tunnel.Encapsulation,              config_parse_fou_encap_type,          0,
 Tunnel.IPv6RapidDeploymentPrefix,  config_parse_6rd_prefix,              0,                             0
 Tunnel.ERSPANIndex,                config_parse_uint32,                  0,                             offsetof(Tunnel, erspan_index)
 Tunnel.SerializeTunneledPackets,   config_parse_tristate,                0,                             offsetof(Tunnel, erspan_sequence)
+Tunnel.ISATAP,                     config_parse_tristate,                0,                             offsetof(Tunnel, isatap)
 FooOverUDP.Protocol,               config_parse_uint8,                   0,                             offsetof(FouTunnel, fou_protocol)
 FooOverUDP.Encapsulation,          config_parse_fou_encap_type,          0,                             offsetof(FouTunnel, fou_encap_type)
 FooOverUDP.Port,                   config_parse_ip_port,                 0,                             offsetof(FouTunnel, port)
index 36f1fe7b03403c959d23422f9727b66010b7a704..684edddb5f5307a1ac25940097cebb7fce63e68a 100644 (file)
@@ -118,6 +118,7 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink
                 r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m");
+
                 /* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is
                  * expecting to receive the prefixlen as a u16.
                  */
@@ -126,6 +127,16 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m");
         }
 
+        if (t->isatap >= 0) {
+                uint16_t flags = 0;
+
+                SET_FLAG(flags, SIT_ISATAP, t->isatap);
+
+                r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+        }
+
         return r;
 }
 
@@ -761,6 +772,7 @@ static void sit_init(NetDev *n) {
         assert(t);
 
         t->pmtudisc = true;
+        t->isatap = -1;
 }
 
 static void vti_init(NetDev *n) {
index 51b61637ad44a92fcf25ed848f7e583d3826a022..8f511dd1f64a90cd8e68ab4a568df925eb25bf3c 100644 (file)
@@ -30,6 +30,7 @@ typedef struct Tunnel {
         int ipv6_flowlabel;
         int allow_localremote;
         int erspan_sequence;
+        int isatap;
 
         unsigned ttl;
         unsigned tos;
index 5296f687a78bc6888ceb47f2a020b62c85b122a6..d575740e83fe5d10fd17c4275482c1619748bf84 100644 (file)
 #include "env-file.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "missing_network.h"
 #include "netlink-util.h"
 #include "network-internal.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
 #include "networkd-ndisc.h"
+#include "networkd-neighbor.h"
 #include "networkd-radv.h"
 #include "networkd-routing-policy-rule.h"
 #include "set.h"
@@ -718,7 +720,7 @@ static void link_enter_configured(Link *link) {
         assert(link);
         assert(link->network);
 
-        if (link->state != LINK_STATE_SETTING_ROUTES)
+        if (link->state != LINK_STATE_CONFIGURING)
                 return;
 
         log_link_info(link, "Configured");
@@ -740,6 +742,12 @@ void link_check_ready(Link *link) {
         if (!link->network)
                 return;
 
+        if (!link->addresses_configured)
+                return;
+
+        if (!link->neighbors_configured)
+                return;
+
         if (!link->static_routes_configured)
                 return;
 
@@ -820,9 +828,8 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
 
         assert(link);
         assert(link->route_messages > 0);
-        assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
-                      LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
-                      LINK_STATE_LINGER));
+        assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
+                      LINK_STATE_FAILED, LINK_STATE_LINGER));
 
         link->route_messages--;
 
@@ -842,7 +849,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         return 1;
 }
 
-static int link_enter_set_routes(Link *link) {
+static int link_request_set_routes(Link *link) {
         enum {
                 PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
                 PHASE_GATEWAY,     /* Second phase: Routes with a gateway */
@@ -853,11 +860,13 @@ static int link_enter_set_routes(Link *link) {
 
         assert(link);
         assert(link->network);
-        assert(link->state == LINK_STATE_SETTING_ADDRESSES);
+        assert(link->addresses_configured);
+        assert(link->address_messages == 0);
+        assert(link->state != _LINK_STATE_INVALID);
 
-        (void) link_set_routing_policy_rule(link);
+        link_set_state(link, LINK_STATE_CONFIGURING);
 
-        link_set_state(link, LINK_STATE_SETTING_ROUTES);
+        (void) link_set_routing_policy_rule(link);
 
         /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */
         for (phase = 0; phase < _PHASE_MAX; phase++)
@@ -885,6 +894,34 @@ static int link_enter_set_routes(Link *link) {
         return 0;
 }
 
+static int link_request_set_neighbors(Link *link) {
+        Neighbor *neighbor;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(link->state != _LINK_STATE_INVALID);
+
+        link_set_state(link, LINK_STATE_CONFIGURING);
+
+        LIST_FOREACH(neighbors, neighbor, link->network->neighbors) {
+                r = neighbor_configure(neighbor, link, NULL);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Could not set neighbor: %m");
+                        link_enter_failed(link);
+                        return r;
+                }
+        }
+
+        if (link->neighbor_messages == 0) {
+                link->neighbors_configured = true;
+                link_check_ready(link);
+        } else
+                log_link_debug(link, "Setting neighbors");
+
+        return 0;
+}
+
 static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -893,7 +930,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         assert(link);
         assert(link->ifname);
         assert(link->address_messages > 0);
-        assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
+        assert(IN_SET(link->state, LINK_STATE_CONFIGURING,
                LINK_STATE_FAILED, LINK_STATE_LINGER));
 
         link->address_messages--;
@@ -909,7 +946,8 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
 
         if (link->address_messages == 0) {
                 log_link_debug(link, "Addresses set");
-                link_enter_set_routes(link);
+                link->addresses_configured = true;
+                link_request_set_routes(link);
         }
 
         return 1;
@@ -1026,7 +1064,7 @@ static int link_set_bridge_fdb(Link *link) {
         return 0;
 }
 
-static int link_enter_set_addresses(Link *link) {
+static int link_request_set_addresses(Link *link) {
         AddressLabel *label;
         Address *ad;
         int r;
@@ -1039,7 +1077,9 @@ static int link_enter_set_addresses(Link *link) {
         if (r < 0)
                 return r;
 
-        link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
+        link_set_state(link, LINK_STATE_CONFIGURING);
+
+        link_request_set_neighbors(link);
 
         LIST_FOREACH(addresses, ad, link->network->static_addresses) {
                 r = address_configure(ad, link, address_handler, false);
@@ -1180,9 +1220,10 @@ static int link_enter_set_addresses(Link *link) {
                 log_link_debug(link, "Offering DHCPv4 leases");
         }
 
-        if (link->address_messages == 0)
-                link_enter_set_routes(link);
-        else
+        if (link->address_messages == 0) {
+                link->addresses_configured = true;
+                link_request_set_routes(link);
+        } else
                 log_link_debug(link, "Setting addresses");
 
         return 0;
@@ -1421,7 +1462,12 @@ static int link_set_bridge(Link *link) {
                 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+        }
 
+        if (link->network->multicast_to_unicast >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
         }
 
         if (link->network->cost != 0) {
@@ -1429,6 +1475,7 @@ static int link_set_bridge(Link *link) {
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
         }
+
         if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
                 r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
                 if (r < 0)
@@ -2262,7 +2309,7 @@ static int link_joined(Link *link) {
         if (!link_has_carrier(link) && !link->network->configure_without_carrier)
                 return 0;
 
-        return link_enter_set_addresses(link);
+        return link_request_set_addresses(link);
 }
 
 static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -2299,7 +2346,7 @@ static int link_enter_join_netdev(Link *link) {
         assert(link->network);
         assert(link->state == LINK_STATE_PENDING);
 
-        link_set_state(link, LINK_STATE_ENSLAVING);
+        link_set_state(link, LINK_STATE_CONFIGURING);
 
         link_dirty(link);
 
@@ -3412,7 +3459,7 @@ static int link_carrier_gained(Link *link) {
                         return r;
                 }
 
-                r = link_enter_set_addresses(link);
+                r = link_request_set_addresses(link);
                 if (r < 0)
                         return r;
         }
@@ -3495,7 +3542,7 @@ int link_update(Link *link, sd_netlink_message *m) {
 
         if (link->state == LINK_STATE_LINGER) {
                 log_link_info(link, "Link readded");
-                link_set_state(link, LINK_STATE_ENSLAVING);
+                link_set_state(link, LINK_STATE_CONFIGURING);
 
                 r = link_new_carrier_maps(link);
                 if (r < 0)
@@ -4023,9 +4070,7 @@ void link_clean(Link *link) {
 
 static const char* const link_state_table[_LINK_STATE_MAX] = {
         [LINK_STATE_PENDING] = "pending",
-        [LINK_STATE_ENSLAVING] = "configuring",
-        [LINK_STATE_SETTING_ADDRESSES] = "configuring",
-        [LINK_STATE_SETTING_ROUTES] = "configuring",
+        [LINK_STATE_CONFIGURING] = "configuring",
         [LINK_STATE_CONFIGURED] = "configured",
         [LINK_STATE_UNMANAGED] = "unmanaged",
         [LINK_STATE_FAILED] = "failed",
index 3fdfa55b25401052f83e4293cff8b665b8555b5d..00e68fdfaab6975d753acc4eee9b52ec0f3368bb 100644 (file)
@@ -19,9 +19,7 @@
 
 typedef enum LinkState {
         LINK_STATE_PENDING,
-        LINK_STATE_ENSLAVING,
-        LINK_STATE_SETTING_ADDRESSES,
-        LINK_STATE_SETTING_ROUTES,
+        LINK_STATE_CONFIGURING,
         LINK_STATE_CONFIGURED,
         LINK_STATE_UNMANAGED,
         LINK_STATE_FAILED,
@@ -72,6 +70,7 @@ typedef struct Link {
 
         unsigned address_messages;
         unsigned address_label_messages;
+        unsigned neighbor_messages;
         unsigned route_messages;
         unsigned routing_policy_rule_messages;
         unsigned routing_policy_rule_remove_messages;
@@ -82,6 +81,8 @@ typedef struct Link {
         Set *routes;
         Set *routes_foreign;
 
+        bool addresses_configured;
+
         sd_dhcp_client *dhcp_client;
         sd_dhcp_lease *dhcp_lease;
         char *lease_file;
@@ -97,6 +98,8 @@ typedef struct Link {
         bool ipv4ll_address:1;
         bool ipv4ll_route:1;
 
+        bool neighbors_configured;
+
         bool static_routes_configured;
         bool routing_policy_rules_configured;
         bool setting_mtu;
index 253308e36cd3129f4aeb6a38fb1806689d649472..8fd6365e68b42870ba5c719d91dcfce59ccc383c 100644 (file)
@@ -8,6 +8,7 @@
 #include "env-file.h"
 #include "fd-util.h"
 #include "hostname-util.h"
+#include "missing_network.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
 #include "parse-util.h"
diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c
new file mode 100644 (file)
index 0000000..254a60b
--- /dev/null
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-netlink.h"
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "ether-addr-util.h"
+#include "hashmap.h"
+#include "in-addr-util.h"
+#include "netlink-util.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "networkd-neighbor.h"
+
+void neighbor_free(Neighbor *neighbor) {
+        if (!neighbor)
+                return;
+
+        if (neighbor->network) {
+                LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor);
+                assert(neighbor->network->n_neighbors > 0);
+                neighbor->network->n_neighbors--;
+
+                if (neighbor->section) {
+                        hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section);
+                        network_config_section_free(neighbor->section);
+                }
+        }
+
+        free(neighbor);
+}
+
+static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) {
+        _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
+        _cleanup_(neighbor_freep) Neighbor *neighbor = NULL;
+        int r;
+
+        assert(network);
+        assert(ret);
+        assert(!!filename == (section_line > 0));
+
+        if (filename) {
+                r = network_config_section_new(filename, section_line, &n);
+                if (r < 0)
+                        return r;
+
+                neighbor = hashmap_get(network->neighbors_by_section, n);
+                if (neighbor) {
+                        *ret = TAKE_PTR(neighbor);
+
+                        return 0;
+                }
+        }
+
+        neighbor = new(Neighbor, 1);
+        if (!neighbor)
+                return -ENOMEM;
+
+        *neighbor = (Neighbor) {
+                .network = network,
+                .family = AF_UNSPEC,
+        };
+
+        LIST_APPEND(neighbors, network->neighbors, neighbor);
+        network->n_neighbors++;
+
+        if (filename) {
+                neighbor->section = TAKE_PTR(n);
+
+                r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops);
+                if (r < 0)
+                        return r;
+
+                r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor);
+                if (r < 0)
+                        return r;
+        }
+
+        *ret = TAKE_PTR(neighbor);
+
+        return 0;
+}
+
+static int neighbor_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+        assert(link->neighbor_messages > 0);
+
+        link->neighbor_messages--;
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0 && r != -EEXIST)
+                log_link_warning_errno(link, r, "Could not set neighbor: %m");
+
+        if (link->neighbor_messages == 0) {
+                log_link_debug(link, "Neighbors set");
+                link->neighbors_configured = true;
+                link_check_ready(link);
+        }
+
+        return 1;
+}
+
+int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(neighbor);
+        assert(link);
+        assert(link->ifindex > 0);
+        assert(link->manager);
+        assert(link->manager->rtnl);
+
+        if (neighbor->family == AF_UNSPEC)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without Address= configured");
+        if (!neighbor->mac_configured)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor without MACAddress= configured");
+
+        r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH,
+                                          link->ifindex, neighbor->family);
+        if (r < 0)
+                return log_error_errno(r, "Could not allocate RTM_NEWNEIGH message: %m");
+
+        r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT);
+        if (r < 0)
+                return log_error_errno(r, "Could not set state: %m");
+
+        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE);
+        if (r < 0)
+                return log_error_errno(r, "Could not set flags: %m");
+
+        r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, &neighbor->mac);
+        if (r < 0)
+                return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m");
+
+        switch (neighbor->family) {
+        case AF_INET6:
+                r = sd_netlink_message_append_in6_addr(req, NDA_DST, &neighbor->in_addr.in6);
+                if (r < 0)
+                        return log_error_errno(r, "Could not append NDA_DST attribute: %m");
+                break;
+        case AF_INET:
+                r = sd_netlink_message_append_in_addr(req, NDA_DST, &neighbor->in_addr.in);
+                if (r < 0)
+                        return log_error_errno(r, "Could not append NDA_DST attribute: %m");
+                break;
+        default:
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Neighbor with invalid address family");
+        }
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_error_errno(r, "Could not send rtnetlink message: %m");
+
+        link->neighbor_messages++;
+        link_ref(link);
+
+        return 0;
+}
+
+int config_parse_neighbor_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 = userdata;
+        _cleanup_(neighbor_freep) Neighbor *n = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = neighbor_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor Address is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        TAKE_PTR(n);
+
+        return 0;
+}
+
+int config_parse_neighbor_hwaddr(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;
+        _cleanup_(neighbor_freep) Neighbor *n = NULL;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = neighbor_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = ether_addr_from_string(rvalue, &n->mac);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor MACAddress is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        n->mac_configured = true;
+        TAKE_PTR(n);
+
+        return 0;
+}
diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h
new file mode 100644 (file)
index 0000000..094bf79
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-netlink.h"
+
+#include "conf-parser.h"
+#include "ether-addr-util.h"
+#include "in-addr-util.h"
+#include "list.h"
+#include "macro.h"
+
+typedef struct Neighbor Neighbor;
+
+#include "networkd-link.h"
+#include "networkd-network.h"
+
+struct Neighbor {
+        Network *network;
+        Link *link;
+        NetworkConfigSection *section;
+
+        int family;
+        union in_addr_union in_addr;
+        bool mac_configured;
+        struct ether_addr mac;
+
+        LIST_FIELDS(Neighbor, neighbors);
+};
+
+void neighbor_free(Neighbor *neighbor);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Neighbor*, neighbor_free);
+
+int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr);
index ed15d221785c4080ce96b4917e09a58d6562854f..00605c0b92683e6f846ba24a21bc1b1be78c1c4c 100644 (file)
@@ -93,6 +93,8 @@ Address.AutoJoin,                       config_parse_address_flags,
 Address.Scope,                          config_parse_address_scope,                     0,                             0
 IPv6AddressLabel.Prefix,                config_parse_address_label_prefix,              0,                             0
 IPv6AddressLabel.Label,                 config_parse_address_label,                     0,                             0
+Neighbor.Address,                       config_parse_neighbor_address,                  0,                             0
+Neighbor.MACAddress,                    config_parse_neighbor_hwaddr,                   0,                             0
 RoutingPolicyRule.TypeOfService,        config_parse_routing_policy_rule_tos,           0,                             0
 RoutingPolicyRule.Priority,             config_parse_routing_policy_rule_priority,      0,                             0
 RoutingPolicyRule.Table,                config_parse_routing_policy_rule_table,         0,                             0
@@ -104,6 +106,7 @@ RoutingPolicyRule.OutgoingInterface,    config_parse_routing_policy_rule_device,
 RoutingPolicyRule.IPProtocol,           config_parse_routing_policy_rule_ip_protocol,   0,                             0
 RoutingPolicyRule.SourcePort,           config_parse_routing_policy_rule_port_range,    0,                             0
 RoutingPolicyRule.DestinationPort,      config_parse_routing_policy_rule_port_range,    0,                             0
+RoutingPolicyRule.InvertRule,           config_parse_routing_policy_rule_invert,        0,                             0
 Route.Gateway,                          config_parse_gateway,                           0,                             0
 Route.Destination,                      config_parse_destination,                       0,                             0
 Route.Source,                           config_parse_destination,                       0,                             0
@@ -162,6 +165,7 @@ Bridge.HairPin,                         config_parse_tristate,
 Bridge.FastLeave,                       config_parse_tristate,                          0,                             offsetof(Network, fast_leave)
 Bridge.AllowPortToBeRoot,               config_parse_tristate,                          0,                             offsetof(Network, allow_port_to_be_root)
 Bridge.UnicastFlood,                    config_parse_tristate,                          0,                             offsetof(Network, unicast_flood)
+Bridge.MulticastToUnicast,              config_parse_tristate,                          0,                             offsetof(Network, multicast_to_unicast)
 Bridge.Priority,                        config_parse_bridge_port_priority,              0,                             offsetof(Network, priority)
 BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,                        0,                             0
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                       0,                             0
index 34378887304e220674b14cc18e4dd0043cefc6eb..6f14fb270ebbfeec618a3da3be8c4a6fc0503380 100644 (file)
@@ -163,6 +163,7 @@ int network_load_one(Manager *manager, const char *filename) {
                 .fast_leave = -1,
                 .allow_port_to_be_root = -1,
                 .unicast_flood = -1,
+                .multicast_to_unicast = -1,
                 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
 
                 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
@@ -209,6 +210,7 @@ int network_load_one(Manager *manager, const char *filename) {
                               "Link\0"
                               "Network\0"
                               "Address\0"
+                              "Neighbor\0"
                               "IPv6AddressLabel\0"
                               "RoutingPolicyRule\0"
                               "Route\0"
@@ -299,6 +301,7 @@ void network_free(Network *network) {
         IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
         RoutingPolicyRule *rule;
         FdbEntry *fdb_entry;
+        Neighbor *neighbor;
         AddressLabel *label;
         Prefix *prefix;
         Address *address;
@@ -349,6 +352,9 @@ void network_free(Network *network) {
         while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
                 ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
 
+        while ((neighbor = network->neighbors))
+                neighbor_free(neighbor);
+
         while ((label = network->address_labels))
                 address_label_free(label);
 
@@ -361,6 +367,7 @@ void network_free(Network *network) {
         hashmap_free(network->addresses_by_section);
         hashmap_free(network->routes_by_section);
         hashmap_free(network->fdb_entries_by_section);
+        hashmap_free(network->neighbors_by_section);
         hashmap_free(network->address_labels_by_section);
         hashmap_free(network->prefixes_by_section);
         hashmap_free(network->rules_by_section);
index 5c1fccbc41e346d26e6957478a3c4a61856963cf..7f64c3883983bba9a125f38482cffcef67320890 100644 (file)
@@ -15,6 +15,7 @@
 #include "networkd-fdb.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-lldp-tx.h"
+#include "networkd-neighbor.h"
 #include "networkd-radv.h"
 #include "networkd-route.h"
 #include "networkd-routing-policy-rule.h"
@@ -183,6 +184,7 @@ struct Network {
         int fast_leave;
         int allow_port_to_be_root;
         int unicast_flood;
+        int multicast_to_unicast;
         uint32_t cost;
         uint16_t priority;
 
@@ -234,6 +236,7 @@ struct Network {
         LIST_HEAD(Route, static_routes);
         LIST_HEAD(FdbEntry, static_fdb_entries);
         LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
+        LIST_HEAD(Neighbor, neighbors);
         LIST_HEAD(AddressLabel, address_labels);
         LIST_HEAD(Prefix, static_prefixes);
         LIST_HEAD(RoutingPolicyRule, rules);
@@ -242,6 +245,7 @@ struct Network {
         unsigned n_static_routes;
         unsigned n_static_fdb_entries;
         unsigned n_ipv6_proxy_ndp_addresses;
+        unsigned n_neighbors;
         unsigned n_address_labels;
         unsigned n_static_prefixes;
         unsigned n_rules;
@@ -249,6 +253,7 @@ struct Network {
         Hashmap *addresses_by_section;
         Hashmap *routes_by_section;
         Hashmap *fdb_entries_by_section;
+        Hashmap *neighbors_by_section;
         Hashmap *address_labels_by_section;
         Hashmap *prefixes_by_section;
         Hashmap *rules_by_section;
index 96013e7026ec1c2c710d896237157880a4289fb7..2dc78622cecf9a7853b7a86271f8c100d6ae00ac 100644 (file)
@@ -588,6 +588,12 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
                         return log_error_errno(r, "Could not append FRA_DPORT_RANGE attribute: %m");
         }
 
+        if (rule->invert_rule) {
+                r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT);
+                if (r < 0)
+                        return log_error_errno(r, "Could not append FIB_RULE_INVERT attribute: %m");
+        }
+
         rule->link = link;
 
         r = netlink_call_async(link->manager->rtnl, NULL, m,
@@ -959,6 +965,45 @@ int config_parse_routing_policy_rule_ip_protocol(
         return 0;
 }
 
+int config_parse_routing_policy_rule_invert(
+                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) {
+
+        _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *n = NULL;
+        Network *network = userdata;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = routing_policy_rule_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        r = parse_boolean(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule invert, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->invert_rule = r;
+
+        n = NULL;
+
+        return 0;
+}
+
 static int routing_policy_rule_read_full_file(const char *state_file, char **ret) {
         _cleanup_free_ char *s = NULL;
         size_t size;
index 0e4215bffdc83ffb350f03b11fd27813c9b59c3b..b35126e2cfd1a2be7252c73d5cba7709801df35c 100644 (file)
@@ -25,6 +25,8 @@ struct RoutingPolicyRule {
         Link *link;
         NetworkConfigSection *section;
 
+        bool invert_rule;
+
         uint8_t tos;
         uint8_t protocol;
 
@@ -79,3 +81,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
 CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
 CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range);
 CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert);
index 4fa5533c6016af0cf2c33278aef3ac57ac9db016..fcecafe08396ff53eba49be02ead21c4577db0ff 100644 (file)
@@ -4,13 +4,16 @@
 #include "sd-event.h"
 
 #include "capability-util.h"
+#include "daemon-util.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "networkd-conf.h"
 #include "networkd-manager.h"
 #include "signal-util.h"
 #include "user-util.h"
 
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+        _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
         _cleanup_(manager_freep) Manager *m = NULL;
         const char *user = "systemd-network";
         uid_t uid;
@@ -21,17 +24,12 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (argc != 1) {
-                log_error("This program takes no arguments.");
-                r = -EINVAL;
-                goto out;
-        }
+        if (argc != 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
 
         r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
-        if (r < 0) {
-                log_error_errno(r, "Cannot resolve user name %s: %m", user);
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Cannot resolve user name %s: %m", user);
 
         /* Create runtime directory. This is not necessary when networkd is
          * started with "RuntimeDirectory=systemd/netif", or after
@@ -49,7 +47,7 @@ int main(int argc, char *argv[]) {
                                     (1ULL << CAP_NET_BROADCAST) |
                                     (1ULL << CAP_NET_RAW));
                 if (r < 0)
-                        goto out;
+                        return log_error_errno(r, "Failed to drop privileges: %m");
         }
 
         /* Always create the directories people can create inotify watches in.
@@ -70,72 +68,50 @@ int main(int argc, char *argv[]) {
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
         r = manager_new(&m);
-        if (r < 0) {
-                log_error_errno(r, "Could not create manager: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not create manager: %m");
 
         r = manager_connect_bus(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not connect to bus: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not connect to bus: %m");
 
         r = manager_parse_config_file(m);
         if (r < 0)
                 log_warning_errno(r, "Failed to parse configuration file: %m");
 
         r = manager_load_config(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not load configuration files: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not load configuration files: %m");
 
         r = manager_rtnl_enumerate_links(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not enumerate links: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not enumerate links: %m");
 
         r = manager_rtnl_enumerate_addresses(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not enumerate addresses: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not enumerate addresses: %m");
 
         r = manager_rtnl_enumerate_routes(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not enumerate routes: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not enumerate routes: %m");
 
         r = manager_rtnl_enumerate_rules(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not enumerate rules: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not enumerate rules: %m");
 
         r = manager_start(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not start manager: %m");
-                goto out;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not start manager: %m");
 
         log_info("Enumeration completed");
 
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing requests...");
+        notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
 
         r = sd_event_loop(m->event);
-        if (r < 0) {
-                log_error_errno(r, "Event loop failed: %m");
-                goto out;
-        }
-out:
-        sd_notify(false,
-                  "STOPPING=1\n"
-                  "STATUS=Shutting down...");
+        if (r < 0)
+                return log_error_errno(r, "Event loop failed: %m");
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 7f30862bbfc79134f4c1e1b17c227ce6744625f8..71b6cf6b87774b83f118725b6cc89563b04bc749 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "sd-daemon.h"
 
+#include "daemon-util.h"
+#include "main-func.h"
 #include "manager.h"
 #include "pretty-print.h"
 #include "signal-util.h"
@@ -14,6 +16,9 @@ static usec_t arg_timeout = 120 * USEC_PER_SEC;
 static char **arg_interfaces = NULL;
 static char **arg_ignore = NULL;
 
+STATIC_DESTRUCTOR_REGISTER(arg_interfaces, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep);
+
 static int help(void) {
         _cleanup_free_ char *link = NULL;
         int r;
@@ -105,7 +110,8 @@ static int parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+        _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -123,37 +129,24 @@ int main(int argc, char *argv[]) {
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
         r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout);
-        if (r < 0) {
-                log_error_errno(r, "Could not create manager: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not create manager: %m");
 
-        if (manager_all_configured(m)) {
-                r = 0;
-                goto finish;
-        }
+        if (manager_all_configured(m))
+                goto success;
 
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Waiting for network connections...");
+        notify_message = notify_start("READY=1\n"
+                                      "STATUS=Waiting for network connections...",
+                                      "STATUS=Failed to wait for network connectivity...");
 
         r = sd_event_loop(m->event);
-        if (r < 0) {
-                log_error_errno(r, "Event loop failed: %m");
-                goto finish;
-        }
-
-finish:
-        strv_free(arg_interfaces);
-        strv_free(arg_ignore);
-
-        if (r >= 0) {
-                sd_notify(false, "STATUS=All interfaces configured...");
+        if (r < 0)
+                return log_error_errno(r, "Event loop failed: %m");
 
-                return EXIT_SUCCESS;
-        } else {
-                sd_notify(false, "STATUS=Failed waiting for network connectivity...");
+success:
+        notify_message = "STATUS=All interfaces configured...";
 
-                return EXIT_FAILURE;
-        }
+        return 0;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 214fa40804c00abba02969cb6ebf7f05bf6a7b0f..9d0f8a9956b3fc47b93728f93915183f397c31da 100644 (file)
@@ -11,6 +11,7 @@
 #include "alloc-util.h"
 #include "ether-addr-util.h"
 #include "lockfile-util.h"
+#include "missing_network.h"
 #include "netlink-util.h"
 #include "nspawn-network.h"
 #include "siphash24.h"
index cb082d163584377cf7f9c7bada8bbc63d574f964..a63aa32e909c247c40882b626b8764c3dc3110bf 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "conf-parser.h"
 #include "macro.h"
-#include "missing.h"
+#include "missing_resource.h"
 #include "nspawn-expose-ports.h"
 #include "nspawn-mount.h"
 
index e865d5b2a824bcc518d298d86e7748ef3bbb83bb..86fd9deec0fee11dd533d8a45589fd977639eabd 100644 (file)
@@ -12,6 +12,7 @@
 #include "mkdir.h"
 #include "nspawn-setuid.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -44,6 +45,8 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
 
                 close_all_fds(NULL, 0);
 
+                (void) rlimit_nofile_safe();
+
                 execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
                 execle("/bin/getent", "getent", database, key, NULL, &empty_env);
                 _exit(EXIT_FAILURE);
index 0fb42d1a74779d42e2c6cb716fb9c8f006e8f37b..03538d1c2f384846fb72d27f13cffc9e5385c4a5 100644 (file)
@@ -6,6 +6,7 @@
 #include <errno.h>
 #include <getopt.h>
 #include <grp.h>
+#include <linux/fs.h>
 #include <linux/loop.h>
 #include <pwd.h>
 #include <sched.h>
@@ -17,7 +18,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/file.h>
-#include <sys/mount.h>
 #include <sys/personality.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
index 88834092bde332cdeebc781c419e7f719cbd2ec5..0b9bae55e7b3435d3416a35b9b764b8908b0ac2d 100644 (file)
@@ -28,7 +28,7 @@ static int makefs(const char *type, const char *device) {
         if (access(mkfs, X_OK) != 0)
                 return log_error_errno(errno, "%s is not executable: %m", mkfs);
 
-        r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+        r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index ec93838538139657618df2faa0c8963f0f21c4ab..3cbdb0b0cc22ded9660717fa1776ba851453e51f 100644 (file)
@@ -7,6 +7,7 @@
 #include "fd-util.h"
 #include "io-util.h"
 #include "machine-image.h"
+#include "missing_capability.h"
 #include "portable.h"
 #include "portabled-bus.h"
 #include "portabled-image-bus.h"
index 77eb2df1180c241f3a98c12fd8d0b695503dbc9f..1e618175c72b24299e0c351578d320f9ab4e1f12 100644 (file)
@@ -8,6 +8,7 @@
 #include "fileio.h"
 #include "io-util.h"
 #include "machine-image.h"
+#include "missing_capability.h"
 #include "portable.h"
 #include "portabled-bus.h"
 #include "portabled-image-bus.h"
index a51a76411e7c56893fee49d91bfa7e30621ebaf6..90f542a058c4928f5df35c72595882a33e1f2fc9 100644 (file)
@@ -78,7 +78,7 @@ static int run(int argc, char *argv[]) {
                         return 0;
         }
 
-        r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+        r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
         if (r < 0)
                 return r;
         if (r == 0) {
index 11f18b1173deb6fbcfc31b52d06540be3982dcd8..cd5510bf12a7d64abc85097623d159b5d473345e 100644 (file)
@@ -21,7 +21,6 @@ static const char *arg_dest = "/tmp";
 
 static int add_symlink(const char *service, const char *where) {
         const char *from, *to;
-        int r;
 
         assert(service);
         assert(where);
@@ -31,8 +30,7 @@ static int add_symlink(const char *service, const char *where) {
 
         (void) mkdir_parents_label(to, 0755);
 
-        r = symlink(from, to);
-        if (r < 0) {
+        if (symlink(from, to) < 0) {
                 if (errno == EEXIST)
                         return 0;
 
@@ -42,6 +40,21 @@ static int add_symlink(const char *service, const char *where) {
         return 1;
 }
 
+static int check_executable(const char *path) {
+        assert(path);
+
+        if (access(path, X_OK) < 0) {
+                if (errno == ENOENT)
+                        return log_debug_errno(errno, "%s does not exist, skipping.", path);
+                if (errno == EACCES)
+                        return log_info_errno(errno, "%s is not marked executable, skipping.", path);
+
+                return log_warning_errno(errno, "Couldn't determine if %s exists and is executable, skipping: %m", path);
+        }
+
+        return 0;
+}
+
 static int run(int argc, char *argv[]) {
         int r = 0, k = 0;
 
@@ -53,19 +66,13 @@ static int run(int argc, char *argv[]) {
         if (argc > 1)
                 arg_dest = argv[1];
 
-        if (access(RC_LOCAL_SCRIPT_PATH_START, X_OK) < 0)
-                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
-                               RC_LOCAL_SCRIPT_PATH_START " is not executable: %m");
-        else {
+        if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) {
                 log_debug("Automatically adding rc-local.service.");
 
                 r = add_symlink("rc-local.service", "multi-user.target");
         }
 
-        if (access(RC_LOCAL_SCRIPT_PATH_STOP, X_OK) < 0)
-                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
-                               RC_LOCAL_SCRIPT_PATH_STOP " is not executable: %m");
-        else {
+        if (check_executable(RC_LOCAL_SCRIPT_PATH_STOP) >= 0) {
                 log_debug("Automatically adding halt-local.service.");
 
                 k = add_symlink("halt-local.service", "final.target");
index 28edbbd856cba1d8fcec727d7f8bc508cc234188..af92ddb96cf5499a22c5a1692d0a9bf6cb7f11c1 100644 (file)
@@ -62,7 +62,7 @@ static int run(int argc, char *argv[]) {
 
                 log_debug("Remounting %s", me->mnt_dir);
 
-                r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+                r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
                 if (r < 0)
                         return r;
                 if (r == 0) {
index 242c26e5caee869c00233206dda19e73b8e18579..383d0b819bdb08e7f017ce8277d72128950d873a 100644 (file)
@@ -212,7 +212,7 @@ int resolvconf_parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Expected interface name as argument.");
 
-        r = ifname_mangle(argv[optind], false);
+        r = ifname_mangle(argv[optind]);
         if (r <= 0)
                 return r;
 
index 1e3fabc450bfa85a8fede5920ffdfc6289ce8a37..8a175ebefc7247a55c9cf2679da64b7776643122 100644 (file)
@@ -16,7 +16,7 @@
 #include "gcrypt-util.h"
 #include "in-addr-util.h"
 #include "main-func.h"
-#include "missing.h"
+#include "missing_network.h"
 #include "netlink-util.h"
 #include "pager.h"
 #include "parse-util.h"
@@ -88,39 +88,26 @@ static int parse_ifindex_and_warn(const char *s) {
         return ifi;
 }
 
-int ifname_mangle(const char *s, bool allow_loopback) {
+int ifname_mangle(const char *s) {
         _cleanup_free_ char *iface = NULL;
         const char *dot;
-        int r;
+        int ifi;
 
         assert(s);
 
-        if (arg_ifname) {
-                assert(arg_ifindex >= 0);
-
-                if (!allow_loopback && arg_ifindex == LOOPBACK_IFINDEX)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Interface can't be the loopback interface (lo). Sorry.");
-
-                return 1;
-        }
-
         dot = strchr(s, '.');
         if (dot) {
+                log_debug("Ignoring protocol specifier '%s'.", dot + 1);
                 iface = strndup(s, dot - s);
-                if (!iface)
-                        return log_oom();
 
-                log_debug("Ignoring protocol specifier '%s'.", dot + 1);
-        } else {
+        } else
                 iface = strdup(s);
-                if (!iface)
-                        return log_oom();
-        }
+        if (!iface)
+                return log_oom();
 
-        if (parse_ifindex(iface, &r) < 0) {
-                r = if_nametoindex(iface);
-                if (r <= 0) {
+        if (parse_ifindex(iface, &ifi) < 0) {
+                ifi = if_nametoindex(iface);
+                if (ifi <= 0) {
                         if (errno == ENODEV && arg_ifindex_permissive) {
                                 log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
                                 return 0; /* done */
@@ -130,12 +117,13 @@ int ifname_mangle(const char *s, bool allow_loopback) {
                 }
         }
 
-        if (!allow_loopback && r == LOOPBACK_IFINDEX)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Interface can't be the loopback interface (lo). Sorry.");
+        if (arg_ifindex > 0 && arg_ifindex != ifi) {
+                log_error("Specified multiple different interfaces. Refusing.");
+                return -EINVAL;
+        }
 
-        arg_ifindex = r;
-        arg_ifname = TAKE_PTR(iface);
+        arg_ifindex = ifi;
+        free_and_replace(arg_ifname, iface);
 
         return 1;
 }
@@ -149,7 +137,7 @@ static void print_source(uint64_t flags, usec_t rtt) {
         if (flags == 0)
                 return;
 
-        fputs("\n-- Information acquired via", stdout);
+        printf("\n%s-- Information acquired via", ansi_grey());
 
         if (flags != 0)
                 printf(" protocol%s%s%s%s%s",
@@ -161,12 +149,24 @@ static void print_source(uint64_t flags, usec_t rtt) {
 
         assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
 
-        printf(" in %s", rtt_str);
+        printf(" in %s.%s\n"
+               "%s-- Data is authenticated: %s%s\n",
+               rtt_str, ansi_normal(),
+               ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal());
+}
+
+static void print_ifindex_comment(int printed_so_far, int ifindex) {
+        char ifname[IF_NAMESIZE];
 
-        fputc('.', stdout);
-        fputc('\n', stdout);
+        if (ifindex <= 0)
+                return;
 
-        printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
+        if (!if_indextoname(ifindex, ifname))
+                log_warning_errno(errno, "Failed to resolve interface name for index %i, ignoring: %m", ifindex);
+        else
+                printf("%*s%s-- link: %s%s",
+                       60 > printed_so_far ? 60 - printed_so_far : 0, " ", /* Align comment to the 60th column */
+                       ansi_grey(), ifname, ansi_normal());
 }
 
 static int resolve_host(sd_bus *bus, const char *name) {
@@ -210,8 +210,7 @@ static int resolve_host(sd_bus *bus, const char *name) {
 
         while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                 _cleanup_free_ char *pretty = NULL;
-                char ifname[IF_NAMESIZE] = "";
-                int ifindex, family;
+                int ifindex, family, k;
                 const void *a;
                 size_t sz;
 
@@ -239,17 +238,16 @@ static int resolve_host(sd_bus *bus, const char *name) {
                         return -EINVAL;
                 }
 
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
                 r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
                 if (r < 0)
                         return log_error_errno(r, "Failed to print address for %s: %m", name);
 
-                printf("%*s%s %s%s%s\n",
-                       (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
-                       pretty,
-                       isempty(ifname) ? "" : "%", ifname);
+                k = printf("%*s%s %s%s%s",
+                           (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
+                           ansi_highlight(), pretty, ansi_normal());
+
+                print_ifindex_comment(k, ifindex);
+                fputc('\n', stdout);
 
                 c++;
         }
@@ -283,7 +281,6 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *pretty = NULL;
-        char ifname[IF_NAMESIZE] = "";
         uint64_t flags;
         unsigned c = 0;
         usec_t ts;
@@ -300,10 +297,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
         if (r < 0)
                 return log_oom();
 
-        if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-        log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
+        log_debug("Resolving %s.", pretty);
 
         r = sd_bus_message_new_method_call(
                         bus,
@@ -341,6 +335,7 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
 
         while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
                 const char *n;
+                int k;
 
                 assert_cc(sizeof(int) == sizeof(int32_t));
 
@@ -352,16 +347,13 @@ static int resolve_address(sd_bus *bus, int family, const union in_addr_union *a
                 if (r < 0)
                         return r;
 
-                ifname[0] = 0;
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
+                k = printf("%*s%s %s%s%s",
+                           (int) strlen(pretty), c == 0 ? pretty : "",
+                           c == 0 ? ":" : " ",
+                           ansi_highlight(), n, ansi_normal());
 
-                printf("%*s%*s%*s%s %s\n",
-                       (int) strlen(pretty), c == 0 ? pretty : "",
-                       isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
-                       (int) strlen(ifname), c == 0 ? ifname : "",
-                       c == 0 ? ":" : " ",
-                       n);
+                print_ifindex_comment(k, ifindex);
+                fputc('\n', stdout);
 
                 c++;
         }
@@ -390,7 +382,6 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) {
         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
         int r;
-        char ifname[IF_NAMESIZE] = "";
 
         r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX);
         if (r < 0)
@@ -416,15 +407,15 @@ static int output_rr_packet(const void *d, size_t l, int ifindex) {
                 fwrite(data, 1, k, stdout);
         } else {
                 const char *s;
+                int k;
 
                 s = dns_resource_record_to_string(rr);
                 if (!s)
                         return log_oom();
 
-                if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                        log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-                printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
+                k = printf("%s", s);
+                print_ifindex_comment(k, ifindex);
+                fputc('\n', stdout);
         }
 
         return 0;
@@ -768,8 +759,7 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons
 
                 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                         _cleanup_free_ char *pretty = NULL;
-                        char ifname[IF_NAMESIZE] = "";
-                        int ifindex, family;
+                        int ifindex, family, k;
                         const void *a;
 
                         assert_cc(sizeof(int) == sizeof(int32_t));
@@ -796,14 +786,13 @@ static int resolve_service(sd_bus *bus, const char *name, const char *type, cons
                                 return -EINVAL;
                         }
 
-                        if (ifindex > 0 && !if_indextoname(ifindex, ifname))
-                                log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
-                        r = in_addr_to_string(family, a, &pretty);
+                        r = in_addr_ifindex_to_string(family, a, ifindex, &pretty);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to print address for %s: %m", name);
 
-                        printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
+                        k = printf("%*s%s", (int) indent, "", pretty);
+                        print_ifindex_comment(k, ifindex);
+                        fputc('\n', stdout);
                 }
                 if (r < 0)
                         return bus_log_parse_error(r);
@@ -1874,14 +1863,16 @@ static int verb_dns(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_DNS);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_DNS);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL);
 
         r = sd_bus_message_new_method_call(
@@ -1958,14 +1949,16 @@ static int verb_domain(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_DOMAIN);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_DOMAIN);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL);
 
         r = sd_bus_message_new_method_call(
@@ -2034,14 +2027,16 @@ static int verb_llmnr(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_LLMNR);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_LLMNR);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL);
 
         r = sd_bus_call_method(bus,
@@ -2073,14 +2068,16 @@ static int verb_mdns(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_MDNS);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_MDNS);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL);
 
         r = sd_bus_call_method(bus,
@@ -2112,14 +2109,16 @@ static int verb_dns_over_tls(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_PRIVATE);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_PRIVATE);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL);
 
         r = sd_bus_call_method(bus,
@@ -2151,14 +2150,16 @@ static int verb_dnssec(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_DNSSEC);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_DNSSEC);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL);
 
         r = sd_bus_call_method(bus,
@@ -2193,14 +2194,16 @@ static int verb_nta(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        if (argc <= 1)
-                return status_all(bus, STATUS_NTA);
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (arg_ifindex <= 0)
+                return status_all(bus, STATUS_NTA);
 
-        if (argc == 2)
+        if (argc < 3)
                 return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL);
 
         /* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors()
@@ -2258,9 +2261,14 @@ static int verb_revert_link(int argc, char **argv, void *userdata) {
 
         assert(bus);
 
-        r = ifname_mangle(argv[1], false);
-        if (r < 0)
-                return r;
+        if (argc >= 2) {
+                r = ifname_mangle(argv[1]);
+                if (r < 0)
+                        return r;
+        }
+
+        if (arg_ifindex <= 0)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface argument required.");
 
         r = sd_bus_call_method(bus,
                                "org.freedesktop.resolve1",
@@ -2501,8 +2509,7 @@ static int compat_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'i':
-                        arg_ifname = mfree(arg_ifname);
-                        r = ifname_mangle(optarg, true);
+                        r = ifname_mangle(optarg);
                         if (r < 0)
                                 return r;
                         break;
@@ -2732,10 +2739,6 @@ static int compat_parse_argv(int argc, char *argv[]) {
                 if (arg_ifindex <= 0)
                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                "--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=.");
-
-                if (arg_ifindex == LOOPBACK_IFINDEX)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Interface can't be the loopback interface (lo). Sorry.");
         }
 
         return 1 /* work to do */;
@@ -2793,8 +2796,7 @@ static int native_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'i':
-                        arg_ifname = mfree(arg_ifname);
-                        r = ifname_mangle(optarg, true);
+                        r = ifname_mangle(optarg);
                         if (r < 0)
                                 return r;
                         break;
@@ -2953,7 +2955,7 @@ static int native_main(int argc, char *argv[], sd_bus *bus) {
                 { "dnsovertls",            VERB_ANY, 3,        0,            verb_dns_over_tls      },
                 { "dnssec",                VERB_ANY, 3,        0,            verb_dnssec           },
                 { "nta",                   VERB_ANY, VERB_ANY, 0,            verb_nta              },
-                { "revert",                2,        2,        0,            verb_revert_link      },
+                { "revert",                VERB_ANY, 2,        0,            verb_revert_link      },
                 {}
         };
 
index 7858fcd6b42dc1fe96bc2ddebd4d6c3891b88cdc..6b3a1f844515f49739b2ccda31d041e87e1e8755 100644 (file)
@@ -26,4 +26,4 @@ extern char **arg_set_dns;
 extern char **arg_set_domain;
 extern bool arg_ifindex_permissive;
 
-int ifname_mangle(const char *s, bool allow_loopback);
+int ifname_mangle(const char *s);
index d80b16c9d989cc5fd9d8711c81fb3851c7b7a6e8..fbe823da66c70a40a394715a09b7558f0c4d7061 100644 (file)
@@ -4,6 +4,7 @@
 #include "bus-common-errors.h"
 #include "bus-util.h"
 #include "dns-domain.h"
+#include "missing_capability.h"
 #include "resolved-bus.h"
 #include "resolved-def.h"
 #include "resolved-dns-synthesize.h"
index ee204435b33964e2759253d69e43de32dec32803..35c3804dbabc98583ce7d42564a68a8f638c0375 100644 (file)
@@ -413,9 +413,25 @@ static int dns_scope_socket(
 
         if (type == SOCK_DGRAM) {
                 /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */
-                r = setsockopt_int(fd, SOL_IP, sa.sa.sa_family == AF_INET ? IP_RECVERR : IPV6_RECVERR, true);
-                if (r < 0)
-                        return r;
+
+                if (sa.sa.sa_family == AF_INET) {
+                        r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true);
+                        if (r < 0)
+                                return r;
+
+                        r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
+                        if (r < 0)
+                                return r;
+
+                } else if (sa.sa.sa_family == AF_INET6) {
+                        r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true);
+                        if (r < 0)
+                                return r;
+
+                        r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         if (ret_socket_address)
index e05ada29a883fdbf9c2cfbd2165d6020e07d6a01..3e69741b8809bb71776af87da558684d76eaf870 100644 (file)
@@ -43,16 +43,18 @@ int dns_server_new(
                         return -E2BIG;
         }
 
-        s = new0(DnsServer, 1);
+        s = new(DnsServer, 1);
         if (!s)
                 return -ENOMEM;
 
-        s->n_ref = 1;
-        s->manager = m;
-        s->type = type;
-        s->family = family;
-        s->address = *in_addr;
-        s->ifindex = ifindex;
+        *s = (DnsServer) {
+                .n_ref = 1,
+                .manager = m,
+                .type = type,
+                .family = family,
+                .address = *in_addr,
+                .ifindex = ifindex,
+        };
 
         dns_server_reset_features(s);
 
@@ -101,7 +103,7 @@ int dns_server_new(
 static DnsServer* dns_server_free(DnsServer *s)  {
         assert(s);
 
-        dns_stream_unref(s->stream);
+        dns_server_unref_stream(s);
 
 #if ENABLE_DNS_OVER_TLS
         dnstls_server_free(s);
@@ -156,6 +158,9 @@ void dns_server_unlink(DnsServer *s) {
         if (s->manager->current_dns_server == s)
                 manager_set_dns_server(s->manager, NULL);
 
+        /* No need to keep a default stream around anymore */
+        dns_server_unref_stream(s);
+
         dns_server_unref(s);
 }
 
@@ -824,6 +829,9 @@ void dns_server_reset_features(DnsServer *s) {
         s->warned_downgrade = false;
 
         dns_server_reset_counters(s);
+
+        /* Let's close the default stream, so that we reprobe with the new features */
+        dns_server_unref_stream(s);
 }
 
 void dns_server_reset_features_all(DnsServer *s) {
@@ -884,6 +892,20 @@ void dns_server_dump(DnsServer *s, FILE *f) {
                 yes_no(s->packet_rrsig_missing));
 }
 
+void dns_server_unref_stream(DnsServer *s) {
+        DnsStream *ref;
+
+        assert(s);
+
+        /* Detaches the default stream of this server. Some special care needs to be taken here, as that stream and
+         * this server reference each other. First, take the stream out of the server. It's destructor will check if it
+         * is registered with us, hence let's invalidate this separatly, so that it is already unregistered. */
+        ref = TAKE_PTR(s->stream);
+
+        /* And then, unref it */
+        dns_stream_unref(ref);
+}
+
 static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
         [DNS_SERVER_SYSTEM] = "system",
         [DNS_SERVER_FALLBACK] = "fallback",
index fda12510495ad8f1a2335273a27a964a8df0d546..6e73f32df45e581ba8784d08edb392069ceb29fd 100644 (file)
@@ -54,6 +54,8 @@ struct DnsServer {
         int ifindex; /* for IPv6 link-local DNS servers */
 
         char *server_string;
+
+        /* The long-lived stream towards this server. */
         DnsStream *stream;
 
 #if ENABLE_DNS_OVER_TLS
@@ -149,3 +151,5 @@ void dns_server_reset_features(DnsServer *s);
 void dns_server_reset_features_all(DnsServer *s);
 
 void dns_server_dump(DnsServer *s, FILE *f);
+
+void dns_server_unref_stream(DnsServer *s);
index 26d4663d746f38999575346e897899543cd6de7f..aee339a4c8d5679349101eccbed4d01e684360ec 100644 (file)
@@ -17,6 +17,9 @@ static void dns_stream_stop(DnsStream *s) {
         s->io_event_source = sd_event_source_unref(s->io_event_source);
         s->timeout_event_source = sd_event_source_unref(s->timeout_event_source);
         s->fd = safe_close(s->fd);
+
+        /* Disconnect us from the server object if we are now not usable anymore */
+        dns_stream_detach(s);
 }
 
 static int dns_stream_update_io(DnsStream *s) {
@@ -46,6 +49,8 @@ static int dns_stream_update_io(DnsStream *s) {
 }
 
 static int dns_stream_complete(DnsStream *s, int error) {
+        _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */
+
         assert(s);
 
 #if ENABLE_DNS_OVER_TLS
@@ -59,6 +64,8 @@ static int dns_stream_complete(DnsStream *s, int error) {
 #endif
                 dns_stream_stop(s);
 
+        dns_stream_detach(s);
+
         if (s->complete)
                 s->complete(s, error);
         else /* the default action if no completion function is set is to close the stream */
@@ -193,7 +200,7 @@ static int dns_stream_identify(DnsStream *s) {
 }
 
 ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags) {
-        ssize_t r;
+        ssize_t m;
 
         assert(s);
         assert(iov);
@@ -203,13 +210,13 @@ ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt,
                 ssize_t ss;
                 size_t i;
 
-                r = 0;
+                m = 0;
                 for (i = 0; i < iovcnt; i++) {
                         ss = dnstls_stream_write(s, iov[i].iov_base, iov[i].iov_len);
                         if (ss < 0)
                                 return ss;
 
-                        r += ss;
+                        m += ss;
                         if (ss != (ssize_t) iov[i].iov_len)
                                 continue;
                 }
@@ -223,28 +230,28 @@ ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt,
                         .msg_namelen = s->tfo_salen
                 };
 
-                r = sendmsg(s->fd, &hdr, MSG_FASTOPEN);
-                if (r < 0) {
+                m = sendmsg(s->fd, &hdr, MSG_FASTOPEN);
+                if (m < 0) {
                         if (errno == EOPNOTSUPP) {
                                 s->tfo_salen = 0;
-                                r = connect(s->fd, &s->tfo_address.sa, s->tfo_salen);
-                                if (r < 0)
+                                if (connect(s->fd, &s->tfo_address.sa, s->tfo_salen) < 0)
                                         return -errno;
 
-                                r = -EAGAIN;
-                        } else if (errno == EINPROGRESS)
-                                r = -EAGAIN;
-                        else
-                                r = -errno;
+                                return -EAGAIN;
+                        }
+                        if (errno == EINPROGRESS)
+                                return -EAGAIN;
+
+                        return -errno;
                 } else
                         s->tfo_salen = 0; /* connection is made */
         } else {
-                r = writev(s->fd, iov, iovcnt);
-                if (r < 0)
-                        r = -errno;
+                m = writev(s->fd, iov, iovcnt);
+                if (m < 0)
+                        return -errno;
         }
 
-        return r;
+        return m;
 }
 
 static ssize_t dns_stream_read(DnsStream *s, void *buf, size_t count) {
@@ -258,7 +265,7 @@ static ssize_t dns_stream_read(DnsStream *s, void *buf, size_t count) {
         {
                 ss = read(s->fd, buf, count);
                 if (ss < 0)
-                        ss = -errno;
+                        return -errno;
         }
 
         return ss;
@@ -273,7 +280,7 @@ static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) {
 }
 
 static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
-        DnsStream *s = userdata;
+        _cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */
         int r;
 
         assert(s);
@@ -281,18 +288,16 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
 #if ENABLE_DNS_OVER_TLS
         if (s->encrypted) {
                 r = dnstls_stream_on_io(s, revents);
-
                 if (r == DNSTLS_STREAM_CLOSED)
                         return 0;
-                else if (r == -EAGAIN)
+                if (r == -EAGAIN)
                         return dns_stream_update_io(s);
-                else if (r < 0) {
+                if (r < 0)
                         return dns_stream_complete(s, -r);
-                } else {
-                        r = dns_stream_update_io(s);
-                        if (r < 0)
-                                return r;
-                }
+
+                r = dns_stream_update_io(s);
+                if (r < 0)
+                        return r;
         }
 #endif
 
@@ -430,9 +435,6 @@ static DnsStream *dns_stream_free(DnsStream *s) {
 
         dns_stream_stop(s);
 
-        if (s->server && s->server->stream == s)
-                s->server->stream = NULL;
-
         if (s->manager) {
                 LIST_REMOVE(streams, s->manager->dns_streams, s);
                 s->manager->n_dns_streams--;
@@ -457,28 +459,37 @@ static DnsStream *dns_stream_free(DnsStream *s) {
 
 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsStream, dns_stream, dns_stream_free);
 
-int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address) {
+int dns_stream_new(
+                Manager *m,
+                DnsStream **ret,
+                DnsProtocol protocol,
+                int fd,
+                const union sockaddr_union *tfo_address) {
+
         _cleanup_(dns_stream_unrefp) DnsStream *s = NULL;
         int r;
 
         assert(m);
+        assert(ret);
         assert(fd >= 0);
 
         if (m->n_dns_streams > DNS_STREAMS_MAX)
                 return -EBUSY;
 
-        s = new0(DnsStream, 1);
+        s = new(DnsStream, 1);
         if (!s)
                 return -ENOMEM;
 
+        *s = (DnsStream) {
+                .n_ref = 1,
+                .fd = -1,
+                .protocol = protocol,
+        };
+
         r = ordered_set_ensure_allocated(&s->write_queue, &dns_packet_hash_ops);
         if (r < 0)
                 return r;
 
-        s->n_ref = 1;
-        s->fd = -1;
-        s->protocol = protocol;
-
         r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s);
         if (r < 0)
                 return r;
@@ -497,15 +508,16 @@ int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd, co
         (void) sd_event_source_set_description(s->timeout_event_source, "dns-stream-timeout");
 
         LIST_PREPEND(streams, m->dns_streams, s);
+        m->n_dns_streams++;
         s->manager = m;
+
         s->fd = fd;
+
         if (tfo_address) {
                 s->tfo_address = *tfo_address;
                 s->tfo_salen = tfo_address->sa.sa_family == AF_INET6 ? sizeof(tfo_address->in6) : sizeof(tfo_address->in);
         }
 
-        m->n_dns_streams++;
-
         *ret = TAKE_PTR(s);
 
         return 0;
@@ -515,6 +527,7 @@ int dns_stream_write_packet(DnsStream *s, DnsPacket *p) {
         int r;
 
         assert(s);
+        assert(p);
 
         r = ordered_set_put(s->write_queue, p);
         if (r < 0)
@@ -524,3 +537,31 @@ int dns_stream_write_packet(DnsStream *s, DnsPacket *p) {
 
         return dns_stream_update_io(s);
 }
+
+DnsPacket *dns_stream_take_read_packet(DnsStream *s) {
+        assert(s);
+
+        if (!s->read_packet)
+                return NULL;
+
+        if (s->n_read < sizeof(s->read_size))
+                return NULL;
+
+        if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size))
+                return NULL;
+
+        s->n_read = 0;
+        return TAKE_PTR(s->read_packet);
+}
+
+void dns_stream_detach(DnsStream *s) {
+        assert(s);
+
+        if (!s->server)
+                return;
+
+        if (s->server->stream != s)
+                return;
+
+        dns_server_unref_stream(s->server);
+}
index 46d2704afefdde6da94d0004628af26ad6faacbb..f18fc919e7399ee81ea922b8df412c85cadab72b 100644 (file)
@@ -53,13 +53,12 @@ struct DnsStream {
         size_t n_written, n_read;
         OrderedSet *write_queue;
 
-        int (*on_connection)(DnsStream *s);
         int (*on_packet)(DnsStream *s);
         int (*complete)(DnsStream *s, int error);
 
         LIST_HEAD(DnsTransaction, transactions); /* when used by the transaction logic */
         DnsServer *server;                       /* when used by the transaction logic */
-        DnsQuery *query;             /* when used by the DNS stub logic */
+        DnsQuery *query;                         /* when used by the DNS stub logic */
 
         /* used when DNS-over-TLS is enabled */
         bool encrypted:1;
@@ -87,3 +86,7 @@ static inline bool DNS_STREAM_QUEUED(DnsStream *s) {
 
         return !!s->write_packet;
 }
+
+DnsPacket *dns_stream_take_read_packet(DnsStream *s);
+
+void dns_stream_detach(DnsStream *s);
index c8c4d829e844840a993ee23f19d657aeb5121be7..a00716cd857072344295911ebd8b09f462857a87 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include "fd-util.h"
+#include "missing_network.h"
 #include "resolved-dns-stub.h"
 #include "socket-util.h"
 
@@ -436,13 +437,17 @@ static int manager_dns_stub_udp_fd(Manager *m) {
 }
 
 static int on_dns_stub_stream_packet(DnsStream *s) {
+        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
+
         assert(s);
-        assert(s->read_packet);
 
-        if (dns_packet_validate_query(s->read_packet) > 0) {
-                log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
+        p = dns_stream_take_read_packet(s);
+        assert(p);
+
+        if (dns_packet_validate_query(p) > 0) {
+                log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p));
 
-                dns_stub_process_query(s->manager, s, s->read_packet);
+                dns_stub_process_query(s->manager, s, p);
         } else
                 log_debug("Invalid DNS stub TCP packet, ignoring.");
 
index 9a8ce7ae2d8dfdbd97ca8216310f86d07bcbec76..f65116c3b45462f93109267c6386aa1422c97ca0 100644 (file)
@@ -3,6 +3,7 @@
 #include "alloc-util.h"
 #include "hostname-util.h"
 #include "local-addresses.h"
+#include "missing_network.h"
 #include "resolved-dns-synthesize.h"
 
 int dns_synthesize_ifindex(int ifindex) {
index ddab2850dfdf113b6ba1004a49ec2e0de56078f7..cc748ac95eac03118e0c5935e26727a8c1cb3e86 100644 (file)
@@ -503,59 +503,54 @@ static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
 }
 
 static int on_stream_complete(DnsStream *s, int error) {
-        _cleanup_(dns_stream_unrefp) DnsStream *p = NULL;
-        DnsTransaction *t, *n;
-        int r = 0;
-
-        /* Do not let new transactions use this stream */
-        if (s->server && s->server->stream == s)
-                p = TAKE_PTR(s->server->stream);
+        assert(s);
 
         if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) {
-                usec_t usec;
-
                 log_debug_errno(error, "Connection failure for DNS TCP stream: %m");
 
                 if (s->transactions) {
+                        DnsTransaction *t;
+
                         t = s->transactions;
-                        assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
                         dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
                 }
         }
 
-        LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
-                if (error != 0)
+        if (error != 0) {
+                DnsTransaction *t, *n;
+
+                LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions)
                         on_transaction_stream_error(t, error);
-                else if (DNS_PACKET_ID(s->read_packet) == t->id)
-                        /* As each transaction have a unique id the return code is only set once */
-                        r = dns_transaction_on_stream_packet(t, s->read_packet);
+        }
 
-        return r;
+        return 0;
 }
 
-static int dns_stream_on_packet(DnsStream *s) {
+static int on_stream_packet(DnsStream *s) {
         _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
-        int r = 0;
         DnsTransaction *t;
 
+        assert(s);
+
         /* Take ownership of packet to be able to receive new packets */
-        p = TAKE_PTR(s->read_packet);
-        s->n_read = 0;
+        p = dns_stream_take_read_packet(s);
+        assert(p);
 
         t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
+        if (t)
+                return dns_transaction_on_stream_packet(t, p);
 
         /* Ignore incorrect transaction id as transaction can have been canceled */
-        if (t)
-                r = dns_transaction_on_stream_packet(t, p);
-        else {
-                if (dns_packet_validate_reply(p) <= 0) {
-                        log_debug("Invalid TCP reply packet.");
-                        on_stream_complete(s, 0);
-                }
-                return 0;
+        if (dns_packet_validate_reply(p) <= 0) {
+                log_debug("Invalid TCP reply packet.");
+                on_stream_complete(s, 0);
         }
 
-        return r;
+        return 0;
+}
+
+static uint16_t dns_port_for_feature_level(DnsServerFeatureLevel level) {
+        return DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? 853 : 53;
 }
 
 static int dns_transaction_emit_tcp(DnsTransaction *t) {
@@ -585,7 +580,7 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
                 if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted))
                         s = dns_stream_ref(t->server->stream);
                 else
-                        fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) ? 853 : 53, &sa);
+                        fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_port_for_feature_level(t->current_feature_level), &sa);
 
                 break;
 
@@ -629,7 +624,9 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
                 fd = -1;
 
 #if ENABLE_DNS_OVER_TLS
-                if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
+                if (t->scope->protocol == DNS_PROTOCOL_DNS &&
+                    DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) {
+
                         assert(t->server);
                         r = dnstls_stream_connect_tls(s, t->server);
                         if (r < 0)
@@ -638,13 +635,13 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
 #endif
 
                 if (t->server) {
-                        dns_stream_unref(t->server->stream);
+                        dns_server_unref_stream(t->server);
                         t->server->stream = dns_stream_ref(s);
                         s->server = dns_server_ref(t->server);
                 }
 
                 s->complete = on_stream_complete;
-                s->on_packet = dns_stream_on_packet;
+                s->on_packet = on_stream_packet;
 
                 /* The interface index is difficult to determine if we are
                  * connecting to the local host, hence fill this in right away
index c2db31df0fdfd8dde3bdbd6249fb02b875e9c34d..24bb37b35e848eaaf59195267ad887046f94b508 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "alloc-util.h"
 #include "bus-util.h"
+#include "missing_capability.h"
 #include "resolved-dnssd.h"
 #include "resolved-dnssd-bus.h"
 #include "resolved-link.h"
index 65f5ceecd01ba860ce7da650bb9ddb1176d8d6d7..dfa55c577c402a1575379ab0f74b041346830c45 100644 (file)
@@ -260,18 +260,21 @@ int manager_llmnr_ipv6_udp_fd(Manager *m) {
 }
 
 static int on_llmnr_stream_packet(DnsStream *s) {
+        _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
         DnsScope *scope;
 
         assert(s);
-        assert(s->read_packet);
 
-        scope = manager_find_scope(s->manager, s->read_packet);
+        p = dns_stream_take_read_packet(s);
+        assert(p);
+
+        scope = manager_find_scope(s->manager, p);
         if (!scope)
                 log_debug("Got LLMNR TCP packet on unknown scope. Ignoring.");
-        else if (dns_packet_validate_query(s->read_packet) > 0) {
-                log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(s->read_packet));
+        else if (dns_packet_validate_query(p) > 0) {
+                log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(p));
 
-                dns_scope_process_query(scope, s, s->read_packet);
+                dns_scope_process_query(scope, s, p);
         } else
                 log_debug("Invalid LLMNR TCP packet, ignoring.");
 
index f6832917c11ae79a1c5f853fe6b9873adef67843..1f8c47ccbebe0a4bb03055292dbcc863a56419d3 100644 (file)
@@ -17,6 +17,7 @@
 #include "fileio.h"
 #include "hostname-util.h"
 #include "io-util.h"
+#include "missing_network.h"
 #include "netlink-util.h"
 #include "network-internal.h"
 #include "ordered-set.h"
index 755477096d59067fd0e4c89dc1c23cea12dc6c43..f4efddf8e5b66ae935d4de18eb84197d724c0f25 100644 (file)
@@ -4,6 +4,8 @@
 #include "sd-event.h"
 
 #include "capability-util.h"
+#include "daemon-util.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "resolved-conf.h"
 #include "resolved-manager.h"
@@ -12,7 +14,8 @@
 #include "signal-util.h"
 #include "user-util.h"
 
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+        _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
         _cleanup_(manager_freep) Manager *m = NULL;
         const char *user = "systemd-resolve";
         uid_t uid;
@@ -21,32 +24,23 @@ int main(int argc, char *argv[]) {
 
         log_setup_service();
 
-        if (argc != 1) {
-                log_error("This program takes no arguments.");
-                r = -EINVAL;
-                goto finish;
-        }
+        if (argc != 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
 
         umask(0022);
 
         r = mac_selinux_init();
-        if (r < 0) {
-                log_error_errno(r, "SELinux setup failed: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "SELinux setup failed: %m");
 
         r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
-        if (r < 0) {
-                log_error_errno(r, "Cannot resolve user name %s: %m", user);
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Cannot resolve user name %s: %m", user);
 
         /* Always create the directory where resolv.conf will live */
         r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE);
-        if (r < 0) {
-                log_error_errno(r, "Could not create runtime directory: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not create runtime directory: %m");
 
         /* Drop privileges, but only if we have been started as root. If we are not running as root we assume most
          * privileges are already dropped. */
@@ -58,22 +52,18 @@ int main(int argc, char *argv[]) {
                                     (UINT64_C(1) << CAP_NET_BIND_SERVICE)| /* needed to bind on port 53 */
                                     (UINT64_C(1) << CAP_SETPCAP)           /* needed in order to drop the caps later */);
                 if (r < 0)
-                        goto finish;
+                        return log_error_errno(r, "Failed to drop privileges: %m");
         }
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0);
 
         r = manager_new(&m);
-        if (r < 0) {
-                log_error_errno(r, "Could not create manager: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not create manager: %m");
 
         r = manager_start(m);
-        if (r < 0) {
-                log_error_errno(r, "Failed to start manager: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to start manager: %m");
 
         /* Write finish default resolv.conf to avoid a dangling symlink */
         (void) manager_write_resolv_conf(m);
@@ -82,27 +72,18 @@ int main(int argc, char *argv[]) {
 
         /* Let's drop the remaining caps now */
         r = capability_bounding_set_drop(0, true);
-        if (r < 0) {
-                log_error_errno(r, "Failed to drop remaining caps: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to drop remaining caps: %m");
 
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Processing requests...");
+        notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
 
         r = sd_event_loop(m->event);
-        if (r < 0) {
-                log_error_errno(r, "Event loop failed: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Event loop failed: %m");
 
-        sd_event_get_exit_code(m->event, &r);
+        (void) sd_event_get_exit_code(m->event, &r);
 
-finish:
-        sd_notify(false,
-                  "STOPPING=1\n"
-                  "STATUS=Shutting down...");
-
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return r;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 27e67df01f01f3e82e06f7468bedef57adf6064f..dbff889e3ead91edc16e82fc547090cce87925f2 100644 (file)
@@ -19,7 +19,7 @@ static void test_parse_etc_hosts_system(void) {
 
         f = fopen("/etc/hosts", "re");
         if (!f) {
-                assert_se(errno == -ENOENT);
+                assert_se(errno == ENOENT);
                 return;
         }
 
index e4eb600ed6c7f39f27d74062a0fe57c9e19128c4..eb07a88ba98ee67091d9777594311d08a343078b 100644 (file)
@@ -2,11 +2,9 @@
 #pragma once
 
 #if HAVE_BLKID
-#include <blkid.h>
-#endif
+#  include <blkid.h>
 
-#include "util.h"
+#  include "macro.h"
 
-#if HAVE_BLKID
 DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
 #endif
index 625bebbe35890ebb214efc0fb78f4f44f8bdcf59..e324a2ffc7fce9f4d5b0f7b9343e3a33e424e276 100644 (file)
@@ -18,6 +18,7 @@
 #include "ip-protocol-list.h"
 #include "list.h"
 #include "locale-util.h"
+#include "missing_fs.h"
 #include "mountpoint-util.h"
 #include "nsflags.h"
 #include "parse-util.h"
index 8110b2cb16884e66bc8f2e0250463365d3780148..8fe177990a6b7ae975f4d9cff0b1d94ad1b19546 100644 (file)
 #include "fs-util.h"
 #include "log.h"
 #include "macro.h"
+#include "missing.h"
 #include "parse-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "socket-util.h"
 #include "string-util.h"
@@ -28,7 +30,6 @@
 #include "syslog-util.h"
 #include "time-util.h"
 #include "utf8.h"
-#include "rlimit-util.h"
 
 int config_item_table_lookup(
                 const void *table,
diff --git a/src/shared/daemon-util.h b/src/shared/daemon-util.h
new file mode 100644 (file)
index 0000000..5e9eca1
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "sd-daemon.h"
+
+#define NOTIFY_READY "READY=1\n" "STATUS=Processing requests..."
+#define NOTIFY_STOPPING "STOPPING=1\n" "STATUS=Shutting down..."
+
+static inline const char *notify_start(const char *start, const char *stop) {
+        if (start)
+                (void) sd_notify(false, start);
+
+        return stop;
+}
+
+/* This is intended to be used with _cleanup_ attribute. */
+static inline void notify_on_cleanup(const char **p) {
+        if (p)
+                (void) sd_notify(false, *p);
+}
index 7ea8ad351c63701d15df8d5e2bbea5ef34da08e9..d66b3004590a12495759cb6d50167b06db27f27d 100644 (file)
@@ -17,6 +17,7 @@
 #include "hashmap.h"
 #include "macro.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "serialize.h"
 #include "set.h"
 #include "signal-util.h"
@@ -52,6 +53,8 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
                                 _exit(EXIT_FAILURE);
                 }
 
+                (void) rlimit_nofile_safe();
+
                 if (!argv) {
                         _argv[0] = (char*) path;
                         _argv[1] = NULL;
index 13591ac892466d744029d1fadc2e9ec2ca700b52..0adaaf2c5671d161fe43d9174b16a6db02490388 100644 (file)
@@ -197,10 +197,9 @@ int generator_write_timeouts(
                 const char *opts,
                 char **filtered) {
 
-        /* Allow configuration how long we wait for a device that
-         * backs a mount point to show up. This is useful to support
-         * endless device timeouts for devices that show up only after
-         * user input, like crypto devices. */
+        /* Configure how long we wait for a device that backs a mount point or a
+         * swap partition to show up. This is useful to support endless device timeouts
+         * for devices that show up only after user input, like crypto devices. */
 
         _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL;
         usec_t u;
index c2abd9956f2d51cd3c2f34f3857322e53d4c127f..e0eef34cdc6d0680cee93f2cd804e14515a01391 100644 (file)
@@ -1,11 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include <stddef.h>
-
-#include "macro.h"
-#include "missing.h"
-
 typedef struct LockFile {
         char *path;
         int fd;
index 4076b9e1d5b3305236ba7b12618fcb2245f65c9b..525a948f3609fc1ee9c2044577e3783b78cb3f7d 100644 (file)
@@ -171,6 +171,10 @@ static bool print_multiline(
                         color_on = ANSI_HIGHLIGHT;
                         color_off = ANSI_NORMAL;
                         highlight_on = ANSI_HIGHLIGHT_RED;
+                } else if (priority >= LOG_DEBUG) {
+                        color_on = ANSI_GREY;
+                        color_off = ANSI_NORMAL;
+                        highlight_on = ANSI_HIGHLIGHT_RED;
                 }
         }
 
index b39ff42b84043f6b055758e2f3782bfccd0dab5c..af06ab22e88bbb6de10cd5cb72dd8f6ad433b14d 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/file.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <linux/fs.h>
index 20a537e3cf19383541fe30feab35b9d6fcbbe976..ca2e05325ee558121324f09aebb81b63ec3c99d3 100644 (file)
@@ -41,6 +41,7 @@ shared_sources = files('''
         cpu-set-util.h
         crypt-util.c
         crypt-util.h
+        daemon-util.h
         dev-setup.c
         dev-setup.h
         dissect-image.c
@@ -120,8 +121,6 @@ shared_sources = files('''
         reboot-util.h
         resolve-util.c
         resolve-util.h
-        rlimit-util.c
-        rlimit-util.h
         seccomp-util.h
         securebits-util.c
         securebits-util.h
index a5beb9200fafbcaeaa01c0a3d798c6cdd0543737..8cc2d0873db2da20252a4f37d0f00c1024512792 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <sched.h>
+#include <errno.h>
 
 #include "alloc-util.h"
 #include "extract-word.h"
index 7cc26a441d4bb44558321cebfc73dac14ae70da5..0aeb0bc89143921538323d86eb12bf74efc718e6 100644 (file)
@@ -1,9 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include <sched.h>
-
-#include "missing.h"
+#include "missing_sched.h"
 
 /* The combination of all namespace flags defined by the kernel. The right type for this isn't clear. setns() and
  * unshare() expect these flags to be passed as (signed) "int", while clone() wants them as "unsigned long". The latter
index 88d9ef349e7ee00d213d35ed60204094ddea4afc..ce4ca9bdb25d63e01dca6312d77e7683a88b9ddb 100644 (file)
@@ -19,6 +19,7 @@
 #include "macro.h"
 #include "pager.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "string-util.h"
 #include "strv.h"
@@ -55,7 +56,7 @@ static int no_quit_on_interrupt(int exe_name_fd, const char *less_opts) {
         file = fdopen(exe_name_fd, "r");
         if (!file) {
                 safe_close(exe_name_fd);
-                return log_debug_errno(errno, "Failed to create FILE object: %m");
+                return log_error_errno(errno, "Failed to create FILE object: %m");
         }
 
         /* Find the last line */
@@ -64,7 +65,7 @@ static int no_quit_on_interrupt(int exe_name_fd, const char *less_opts) {
 
                 r = read_line(file, LONG_LINE_MAX, &t);
                 if (r < 0)
-                        return r;
+                        return log_error_errno(r, "Failed to read from socket: %m");
                 if (r == 0)
                         break;
 
@@ -96,7 +97,7 @@ int pager_open(PagerFlags flags) {
                 return 0;
 
         if (!is_main_thread())
-                return -EPERM;
+                return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Pager invoked from wrong thread.");
 
         pager = getenv("SYSTEMD_PAGER");
         if (!pager)
@@ -105,7 +106,7 @@ int pager_open(PagerFlags flags) {
         if (pager) {
                 pager_args = strv_split(pager, WHITESPACE);
                 if (!pager_args)
-                        return -ENOMEM;
+                        return log_oom();
 
                 /* If the pager is explicitly turned off, honour it */
                 if (strv_isempty(pager_args) || strv_equal(pager_args, STRV_MAKE("cat")))
@@ -131,7 +132,7 @@ int pager_open(PagerFlags flags) {
         if (flags & PAGER_JUMP_TO_END)
                 less_opts = strjoina(less_opts, " +G");
 
-        r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pager_pid);
+        r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pager_pid);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -139,11 +140,17 @@ int pager_open(PagerFlags flags) {
 
                 /* In the child start the pager */
 
-                (void) dup2(fd[0], STDIN_FILENO);
+                if (dup2(fd[0], STDIN_FILENO) < 0) {
+                        log_error_errno(errno, "Failed to duplicate file descriptor to STDIN: %m");
+                        _exit(EXIT_FAILURE);
+                }
+
                 safe_close_pair(fd);
 
-                if (setenv("LESS", less_opts, 1) < 0)
+                if (setenv("LESS", less_opts, 1) < 0) {
+                        log_error_errno(errno, "Failed to set environment variable LESS: %m");
                         _exit(EXIT_FAILURE);
+                }
 
                 /* Initialize a good charset for less. This is
                  * particularly important if we output UTF-8
@@ -152,14 +159,21 @@ int pager_open(PagerFlags flags) {
                 if (!less_charset && is_locale_utf8())
                         less_charset = "utf-8";
                 if (less_charset &&
-                    setenv("LESSCHARSET", less_charset, 1) < 0)
+                    setenv("LESSCHARSET", less_charset, 1) < 0) {
+                        log_error_errno(errno, "Failed to set environment variable LESSCHARSET: %m");
                         _exit(EXIT_FAILURE);
+                }
 
                 if (pager_args) {
-                        if (loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false) < 0)
+                        r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to write pager name to socket: %m");
                                 _exit(EXIT_FAILURE);
+                        }
 
                         execvp(pager_args[0], pager_args);
+                        log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
+                                       "Failed execute %s, using fallback pagers: %m", pager_args[0]);
                 }
 
                 /* Debian's alternatives command for pagers is
@@ -169,13 +183,21 @@ int pager_open(PagerFlags flags) {
                  * is similar to this one anyway, but is
                  * Debian-specific. */
                 FOREACH_STRING(exe, "pager", "less", "more") {
-                        if (loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false) < 0)
+                        r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false);
+                        if (r  < 0) {
+                                log_error_errno(r, "Failed to write pager name to socket: %m");
                                 _exit(EXIT_FAILURE);
+                        }
                         execlp(exe, exe, NULL);
+                        log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
+                                       "Failed execute %s, using next fallback pager: %m", exe);
                 }
 
-                if (loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false) < 0)
+                r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in") + 1, false);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to write pager name to socket: %m");
                         _exit(EXIT_FAILURE);
+                }
                 pager_fallback();
                 /* not reached */
         }
@@ -256,7 +278,7 @@ int show_man_page(const char *desc, bool null_stdio) {
         } else
                 args[1] = desc;
 
-        r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_LOG, &pid);
+        r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index 82481972f08dd8269c00c30c21a8b6f36f4d65e6..6d65efbb9ea55ab691f1566bca06ba43ca48a5fe 100644 (file)
@@ -69,7 +69,7 @@ static int fork_wait(const char* const cmdline[]) {
         pid_t pid;
         int r;
 
-        r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+        r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index be6627a3e68f16e8f1ea1964512325a816ca71e4..40fcb2cae3ef962b3970516385972dc050af5206 100644 (file)
@@ -1,7 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
-/***
-  Copyright © 2013 Marc-Antoine Perennou
-***/
 
 #include <errno.h>
 #include <fcntl.h>
@@ -2802,63 +2799,87 @@ static void wait_context_free(WaitContext *c) {
 }
 
 static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        const char *path, *interface, *active_state = NULL, *job_path = NULL;
         WaitContext *c = userdata;
-        const char *path;
+        bool is_failed;
         int r;
 
+        /* Called whenever we get a PropertiesChanged signal. Checks if ActiveState changed to inactive/failed.
+         *
+         * Signal parameters: (s interface, a{sv} changed_properties, as invalidated_properties) */
+
         path = sd_bus_message_get_path(m);
         if (!set_contains(c->unit_paths, path))
                 return 0;
 
-        /* Check if ActiveState changed to inactive/failed */
-        /* (s interface, a{sv} changed_properties, as invalidated_properties) */
-        r = sd_bus_message_skip(m, "s");
+        r = sd_bus_message_read(m, "s", &interface);
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        if (!streq(interface, "org.freedesktop.systemd1.Unit")) /* ActiveState is on the Unit interface */
+                return 0;
+
         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
         if (r < 0)
                 return bus_log_parse_error(r);
 
-        while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
+        for (;;) {
                 const char *s;
 
-                r = sd_bus_message_read(m, "s", &s);
+                r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv");
                 if (r < 0)
                         return bus_log_parse_error(r);
+                if (r == 0) /* end of array */
+                        break;
 
-                if (streq(s, "ActiveState")) {
-                        bool is_failed;
+                r = sd_bus_message_read(m, "s", &s); /* Property name */
+                if (r < 0)
+                        return bus_log_parse_error(r);
 
-                        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
+                if (streq(s, "ActiveState")) {
+                        r = sd_bus_message_read(m, "v", "s", &active_state);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        r = sd_bus_message_read(m, "s", &s);
+                        if (job_path) /* Found everything we need */
+                                break;
+
+                } else if (streq(s, "Job")) {
+                        uint32_t job_id;
+
+                        r = sd_bus_message_read(m, "v", "(uo)", &job_id, &job_path);
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
-                        is_failed = streq(s, "failed");
-                        if (streq(s, "inactive") || is_failed) {
-                                log_debug("%s became %s, dropping from --wait tracking", path, s);
-                                free(set_remove(c->unit_paths, path));
-                                c->any_failed = c->any_failed || is_failed;
-                        } else
-                                log_debug("ActiveState on %s changed to %s", path, s);
+                        /* There's still a job pending for this unit, let's ignore this for now, and return right-away. */
+                        if (job_id != 0)
+                                return 0;
+
+                        if (active_state) /* Found everything we need */
+                                break;
 
-                        break; /* no need to dissect the rest of the message */
                 } else {
-                        /* other property */
-                        r = sd_bus_message_skip(m, "v");
+                        r = sd_bus_message_skip(m, "v"); /* Other property */
                         if (r < 0)
                                 return bus_log_parse_error(r);
                 }
+
                 r = sd_bus_message_exit_container(m);
                 if (r < 0)
                         return bus_log_parse_error(r);
         }
-        if (r < 0)
-                return bus_log_parse_error(r);
+
+        /* If this didn't contain the ActiveState property we can't do anything */
+        if (!active_state)
+                return 0;
+
+        is_failed = streq(active_state, "failed");
+        if (streq(active_state, "inactive") || is_failed) {
+                log_debug("%s became %s, dropping from --wait tracking", path, active_state);
+                free(set_remove(c->unit_paths, path));
+                c->any_failed = c->any_failed || is_failed;
+        } else
+                log_debug("ActiveState on %s changed to %s", path, active_state);
 
         if (set_isempty(c->unit_paths))
                 sd_event_exit(c->event, EXIT_SUCCESS);
@@ -3069,6 +3090,7 @@ static int start_unit(int argc, char *argv[], void *userdata) {
         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_(wait_context_free) WaitContext wait_context = {};
         const char *method, *mode, *one_name, *suffix = NULL;
+        _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */
         _cleanup_strv_free_ char **names = NULL;
         int r, ret = EXIT_SUCCESS;
         sd_bus *bus;
@@ -3165,6 +3187,12 @@ static int start_unit(int argc, char *argv[], void *userdata) {
                 r = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
                 if (ret == EXIT_SUCCESS && r < 0)
                         ret = translate_bus_error_to_exit_status(r, &error);
+
+                if (r >= 0 && streq(method, "StopUnit")) {
+                        r = strv_push(&stopped_units, *name);
+                        if (r < 0)
+                                return log_oom();
+                }
         }
 
         if (!arg_no_block) {
@@ -3189,8 +3217,8 @@ static int start_unit(int argc, char *argv[], void *userdata) {
 
                 /* When stopping units, warn if they can still be triggered by
                  * another active unit (socket, path, timer) */
-                if (!arg_quiet && streq(method, "StopUnit"))
-                        STRV_FOREACH(name, names)
+                if (!arg_quiet)
+                        STRV_FOREACH(name, stopped_units)
                                 (void) check_triggering_units(bus, *name);
         }
 
@@ -3532,7 +3560,7 @@ static int load_kexec_kernel(void) {
         if (arg_dry_run)
                 return 0;
 
-        r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+        r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -6005,7 +6033,7 @@ static int enable_sysv_units(const char *verb, char **args) {
                 if (!arg_quiet)
                         log_info("Executing: %s", l);
 
-                j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+                j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
                 if (j < 0)
                         return j;
                 if (j == 0) {
@@ -6900,7 +6928,7 @@ static int run_editor(char **paths) {
 
         assert(paths);
 
-        r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
+        r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -7552,7 +7580,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
         arg_ask_password = true;
 
-        while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir.::", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -7868,6 +7896,14 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                                 return log_oom();
                         break;
 
+                case '.':
+                        /* Output an error mimicking getopt, and print a hint afterwards */
+                        log_error("%s: invalid option -- '.'", program_invocation_name);
+                        log_notice("Hint: to specify units starting with a dash, use \"--\":\n"
+                                   "      %s [OPTIONS...] {COMMAND} -- -.%s ...",
+                                   program_invocation_name, optarg ?: "mount");
+                        _fallthrough_;
+
                 case '?':
                         return -EINVAL;
 
@@ -8302,6 +8338,7 @@ static int parse_argv(int argc, char *argv[]) {
                                 /* Hmm, so some other init system is running, we need to forward this request to
                                  * it. For now we simply guess that it is Upstart. */
 
+                                (void) rlimit_nofile_safe();
                                 execv(TELINIT, argv);
 
                                 return log_error_errno(SYNTHETIC_ERRNO(EIO),
index 20bff2838e2fb942f1fd9031d670e0b6dc3d7863..30be5b113ca36e6c40241b72873536cebd37272a 100644 (file)
@@ -179,6 +179,8 @@ int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message
 int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char *len);
 int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type);
 int sd_rtnl_message_routing_policy_rule_get_rtm_type(sd_netlink_message *m, unsigned char *type);
+int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags);
+int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags);
 
 /* genl */
 int sd_genl_socket_open(sd_netlink **nl);
index 9803c53f212a5caac8996132ef4073d3f29a8253..3005fc1b696bc47eb151d0f1154871c25bb158e8 100644 (file)
@@ -4,8 +4,8 @@
 #include <string.h>
 
 #include "macro.h"
+#include "missing_network.h"
 #include "string-util.h"
-#include "util.h"
 
 _unused_ \
 static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len);
index f902f500e0cc349052a0572bb88ce58498bb94b1..07ff4878340f057d8dfd10733e4f4613b67ffd42 100644 (file)
@@ -13,6 +13,7 @@
 #include "io-util.h"
 #include "log.h"
 #include "macro.h"
+#include "missing_network.h"
 #include "process-util.h"
 #include "socket-util.h"
 #include "string-util.h"
index 28dadd0c5b4219651a1d0ad7e8a11ac689f34d74..83a66e8772382cfb05da9e5b4a91e272d5ed392d 100755 (executable)
@@ -1,10 +1,10 @@
 #!/usr/bin/env python3
-#  SPDX-License-Identifier: LGPL-2.1+
+# 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.
+# 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.
 
 import os
 import sys
index 405529555564647e5f7173fff07b641b0f63bfc9..70774d757beff0241c9d734b4d59fb835090688c 100644 (file)
@@ -5,8 +5,10 @@
 
 #include "capability-util.h"
 #include "clock-util.h"
+#include "daemon-util.h"
 #include "fd-util.h"
 #include "fs-util.h"
+#include "main-func.h"
 #include "mkdir.h"
 #include "network-util.h"
 #include "process-util.h"
@@ -83,7 +85,8 @@ settime:
         return 0;
 }
 
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
+        _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
         _cleanup_(manager_freep) Manager *m = NULL;
         const char *user = "systemd-timesync";
         uid_t uid, uid_current;
@@ -95,48 +98,39 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (argc != 1) {
-                log_error("This program does not take arguments.");
-                r = -EINVAL;
-                goto finish;
-        }
+        if (argc != 1)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program does not take arguments.");
 
         uid = uid_current = geteuid();
         gid = getegid();
 
         if (uid_current == 0) {
                 r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
-                if (r < 0) {
-                        log_error_errno(r, "Cannot resolve user name %s: %m", user);
-                        goto finish;
-                }
+                if (r < 0)
+                        return log_error_errno(r, "Cannot resolve user name %s: %m", user);
         }
 
         r = load_clock_timestamp(uid, gid);
         if (r < 0)
-                goto finish;
+                return r;
 
         /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all
          * privileges are already dropped. */
         if (uid_current == 0) {
                 r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME));
                 if (r < 0)
-                        goto finish;
+                        return log_error_errno(r, "Failed to drop privileges: %m");
         }
 
         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
 
         r = manager_new(&m);
-        if (r < 0) {
-                log_error_errno(r, "Failed to allocate manager: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate manager: %m");
 
         r = manager_connect_bus(m);
-        if (r < 0) {
-                log_error_errno(r, "Could not connect to bus: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Could not connect to bus: %m");
 
         if (clock_is_localtime(NULL) > 0) {
                 log_info("The system is configured to read the RTC time in the local time zone. "
@@ -149,27 +143,24 @@ int main(int argc, char *argv[]) {
                 log_warning_errno(r, "Failed to parse configuration file: %m");
 
         r = manager_parse_fallback_string(m, NTP_SERVERS);
-        if (r < 0) {
-                log_error_errno(r, "Failed to parse fallback server strings: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse fallback server strings: %m");
 
         log_debug("systemd-timesyncd running as pid " PID_FMT, getpid_cached());
-        sd_notify(false,
-                  "READY=1\n"
-                  "STATUS=Daemon is running");
+
+        notify_message = notify_start("READY=1\n"
+                                      "STATUS=Daemon is running",
+                                      NOTIFY_STOPPING);
 
         if (network_is_online()) {
                 r = manager_connect(m);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
 
         r = sd_event_loop(m->event);
-        if (r < 0) {
-                log_error_errno(r, "Failed to run event loop: %m");
-                goto finish;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to run event loop: %m");
 
         /* if we got an authoritative time, store it in the file system */
         if (m->sync) {
@@ -178,12 +169,9 @@ int main(int argc, char *argv[]) {
                         log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE);
         }
 
-        sd_event_get_exit_code(m->event, &r);
-
-finish:
-        sd_notify(false,
-                  "STOPPING=1\n"
-                  "STATUS=Shutting down...");
+        (void) sd_event_get_exit_code(m->event, &r);
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return r;
 }
+
+DEFINE_MAIN_FUNCTION(run);
index 93d4ea4d3f38046a8ad09fc7ec8a252cc4396d97..e4bc5161d5848673870c15b4b94ce6301ff18910 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/ethtool.h>
 
 #include "conf-parser.h"
-#include "missing.h"
+#include "missing_network.h"
 
 struct link_config;
 
index f2238ae14edd8e6686dd79ddb423956c58f5f266..d90ebb72599fdfbdf147f02d7c9c9e2d4b5685ea 100644 (file)
@@ -24,6 +24,7 @@
 #include "socket-util.h"
 #include "strxcpyx.h"
 #include "udev-ctrl.h"
+#include "util.h"
 
 /* wire protocol magic must match */
 #define UDEV_CTRL_MAGIC                                0xdead1dea
index 3782d892c2df5882c338d73dbde4fcaa58c41c92..bb3e1b9f2381f72d03796eddc8ee740fc606d3c0 100644 (file)
@@ -20,6 +20,7 @@
 #include "netlink-util.h"
 #include "path-util.h"
 #include "process-util.h"
+#include "rlimit-util.h"
 #include "signal-util.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -650,6 +651,7 @@ int udev_event_spawn(struct udev_event *event,
                         _exit(EXIT_FAILURE);
 
                 (void) close_all_fds(NULL, 0);
+                (void) rlimit_nofile_safe();
 
                 execve(argv[0], argv, envp);
                 _exit(EXIT_FAILURE);
index c9e3d426b30a17f06de59817b408a8f0ff09c988..fa85f6e2632dc10f74bb15c922d2c3c2901ca4fe 100644 (file)
@@ -534,7 +534,7 @@ static int worker_spawn(Manager *manager, struct event *event) {
         if (r < 0)
                 return log_error_errno(r, "Worker: Failed to enable receiving of device: %m");
 
-        r = safe_fork(NULL, FORK_DEATHSIG, &pid);
+        r = safe_fork("(worker)", FORK_DEATHSIG, &pid);
         if (r < 0) {
                 event->state = EVENT_QUEUED;
                 return log_error_errno(r, "Failed to fork() worker: %m");
@@ -1850,7 +1850,7 @@ static int run(int argc, char *argv[]) {
                         return 0;
 
                 /* child */
-                setsid();
+                (void) setsid();
 
                 r = set_oom_score_adjust(-1000);
                 if (r < 0)
index 71fc59cbfada9a55919937b6154f21e1ab1c9d11..efaa8c28d390e9549e167abc11b204d358fb8a03 100644 (file)
@@ -150,7 +150,7 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
                 log_debug("Executing \"%s\"...", strnull(cmd));
         }
 
-        r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+        r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -193,7 +193,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
                 log_debug("Executing \"%s\"...", strnull(cmd));
         }
 
-        r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+        r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
index 19226df80621846226a4889e684b0b405120981b..5a8d41eb68385e2949940b80752062eb4207e492 100644 (file)
@@ -76,6 +76,7 @@ FOUSourcePort=
 IPv6RapidDeploymentPrefix=
 ERSPANIndex=
 SerializeTunneledPackets=
+ISATAP=
 [VXLAN]
 UDP6ZeroChecksumRx=
 ARPProxy=
diff --git a/test/fuzz/fuzz-network-parser/25-neighbor-section.network b/test/fuzz/fuzz-network-parser/25-neighbor-section.network
new file mode 100644 (file)
index 0000000..dd750dd
--- /dev/null
@@ -0,0 +1,6 @@
+[Match]
+Name=dummy98
+
+[Neighbor]
+Address=2004:da8:1:0::
+MACAddress=00:00:5e:00:02:00
index 84f221d538549aaaeec91bf1276f66ff57d4d6b2..81b372fb6d091e78dadd8762001f360544f8d51b 100644 (file)
@@ -9,3 +9,4 @@ Cost=400
 HairPin = true
 FastLeave = true
 UnicastFlood = true
+MulticastToUnicast = true
index 8ea809a7e1f1ebdf9f6fdd5f31451877411de7e0..cab87bf98f2e632ab7dcc49cd3d4b746dde35428 100644 (file)
@@ -6,6 +6,7 @@ UnicastFlood=
 FastLeave=
 Priority=
 AllowPortToBeRoot=
+MulticastToUnicast=
 [Match]
 KernelVersion=
 Type=
@@ -153,6 +154,7 @@ FirewallMark=
 SourcePort=
 DestinationPort=
 IPProtocol=
+InvertRule=
 [IPv6PrefixDelegation]
 RouterPreference=
 DNSLifetimeSec=
@@ -163,6 +165,9 @@ EmitDNS=
 EmitDomains=
 Managed=
 OtherInformation=
+[Neighbor]
+Address=
+MacAddress=
 [IPv6AddressLabel]
 Label=
 Prefix=
index f454fd313ec63044a4ac823bc509f28a43817bc2..4d7526f63619d37f626f9270d654ce5c8e34f385 100644 (file)
@@ -417,6 +417,7 @@ Group=
 GroupForwardMask=
 GroupPolicyExtension=
 HairPin=
+MulticastToUnicast=
 HelloTimeSec=
 HomeAddress=
 Host=
@@ -442,6 +443,7 @@ Independent=
 InitialAdvertisedReceiveWindow=
 InitialCongestionWindow=
 InputKey=
+InvertRule=
 KernelCommandLine=
 KernelVersion=
 Key=
diff --git a/test/test-network/conf/25-fibrule-invert.network b/test/test-network/conf/25-fibrule-invert.network
new file mode 100644 (file)
index 0000000..bcca0c2
--- /dev/null
@@ -0,0 +1,10 @@
+[Match]
+Name=test1
+
+[RoutingPolicyRule]
+TypeOfService=0x08
+Table=7
+From= 192.168.100.18
+Priority=111
+IPProtocol = tcp
+InvertRule=true
diff --git a/test/test-network/conf/25-isatap-tunnel.netdev b/test/test-network/conf/25-isatap-tunnel.netdev
new file mode 100644 (file)
index 0000000..3aa882a
--- /dev/null
@@ -0,0 +1,8 @@
+[NetDev]
+Name=isataptun99
+Kind=sit
+
+[Tunnel]
+Local=10.65.223.238
+Remote=10.65.223.239
+ISATAP=true
diff --git a/test/test-network/conf/25-neighbor-section.network b/test/test-network/conf/25-neighbor-section.network
new file mode 100644 (file)
index 0000000..d90802f
--- /dev/null
@@ -0,0 +1,10 @@
+[Match]
+Name=dummy98
+
+[Neighbor]
+Address=192.168.10.1
+MACAddress=00:00:5e:00:02:65
+
+[Neighbor]
+Address=2004:da8:1:0::1
+MACAddress=00:00:5e:00:02:66
index 84f221d538549aaaeec91bf1276f66ff57d4d6b2..81b372fb6d091e78dadd8762001f360544f8d51b 100644 (file)
@@ -9,3 +9,4 @@ Cost=400
 HairPin = true
 FastLeave = true
 UnicastFlood = true
+MulticastToUnicast = true
diff --git a/test/test-network/conf/isatap.network b/test/test-network/conf/isatap.network
new file mode 100644 (file)
index 0000000..e8d03ed
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=dummy98
+
+[Network]
+Tunnel=isataptun99
index 806f4a496c4930e0499609583afed13d8dc4e9c6..65cc43e8b6b2b3bbed5454b9b878d9090b63da35 100755 (executable)
@@ -3,15 +3,15 @@
 # systemd-networkd tests
 
 import os
-import sys
-import unittest
-import subprocess
-import time
 import re
 import shutil
 import signal
 import socket
+import subprocess
+import sys
 import threading
+import time
+import unittest
 from shutil import copytree
 
 network_unit_file_path='/run/systemd/network'
@@ -61,6 +61,15 @@ class Utilities():
         with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
             return f.readline().strip()
 
+    def read_bridge_port_attr(self, bridge, link, attribute):
+
+        path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
+        path_port = 'lower_' + link + '/brport'
+        path = os.path.join(path_bridge, path_port)
+
+        with open(os.path.join(path, attribute)) as f:
+            return f.readline().strip()
+
     def link_exits(self, link):
         return os.path.exists(os.path.join('/sys/class/net', link))
 
@@ -104,15 +113,16 @@ class Utilities():
 
             os.remove(pid_file)
 
-    def search_words_in_file(self, word):
+    def search_words_in_dnsmasq_log(self, words, show_all=False):
         if os.path.exists(dnsmasq_log_file):
             with open (dnsmasq_log_file) as in_file:
                 contents = in_file.read()
-                print(contents)
-                for part in contents.split():
-                    if word in part:
+                if show_all:
+                    print(contents)
+                for line in contents.split('\n'):
+                    if words in line:
                         in_file.close()
-                        print("%s, %s" % (word, part))
+                        print("%s, %s" % (words, line))
                         return True
         return False
 
@@ -132,6 +142,7 @@ class Utilities():
         else:
             subprocess.check_call('systemctl restart systemd-networkd', shell=True)
         time.sleep(5)
+        print()
 
 global ip
 global port
@@ -162,21 +173,82 @@ class DHCPServer(threading.Thread):
 
 class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
-    links =['bridge99', 'bond99', 'bond99', 'vlan99', 'test1', 'macvtap99',
-            'macvlan99', 'ipvlan99', 'vxlan99', 'veth99', 'vrf99', 'tun99',
-            'tap99', 'vcan99', 'geneve99', 'dummy98', 'ipiptun99', 'sittun99', '6rdtun99',
-            'gretap99', 'vtitun99', 'vti6tun99','ip6tnl99', 'gretun99', 'ip6gretap99',
-            'wg99', 'dropin-test', 'erspan-test']
-
-    units = ['25-bridge.netdev', '25-bond.netdev', '21-vlan.netdev', '11-dummy.netdev', '21-vlan.network',
-             '21-macvtap.netdev', 'macvtap.network', '21-macvlan.netdev', 'macvlan.network', 'vxlan.network',
-             '25-vxlan.netdev', '25-ipvlan.netdev', 'ipvlan.network', '25-veth.netdev', '25-vrf.netdev',
-             '25-tun.netdev', '25-tun.netdev', '25-vcan.netdev', '25-geneve.netdev', '25-ipip-tunnel.netdev',
-             '25-ip6tnl-tunnel.netdev', '25-ip6gre-tunnel.netdev', '25-sit-tunnel.netdev', '25-6rd-tunnel.netdev',
-             '25-erspan-tunnel.netdev', '25-gre-tunnel.netdev', '25-gretap-tunnel.netdev', '25-vti-tunnel.netdev',
-             '25-vti6-tunnel.netdev', '12-dummy.netdev', 'gre.network', 'ipip.network', 'ip6gretap.network',
-             'gretun.network', 'ip6tnl.network', '25-tap.netdev', 'vti6.network', 'vti.network', 'gretap.network',
-             'sit.network', '25-ipip-tunnel-independent.netdev', '25-wireguard.netdev', '6rd.network', '10-dropin-test.netdev']
+    links =[
+        '6rdtun99',
+        'bond99',
+        'bridge99',
+        'dropin-test',
+        'dummy98',
+        'erspan-test',
+        'geneve99',
+        'gretap99',
+        'gretun99',
+        'ip6gretap99',
+        'ip6tnl99',
+        'ipiptun99',
+        'ipvlan99',
+        'isataptun99',
+        'macvlan99',
+        'macvtap99',
+        'sittun99',
+        'tap99',
+        'test1',
+        'tun99',
+        'vcan99',
+        'veth99',
+        'vlan99',
+        'vrf99',
+        'vti6tun99',
+        'vtitun99',
+        'vxlan99',
+        'wg99']
+
+    units = [
+        '10-dropin-test.netdev',
+        '11-dummy.netdev',
+        '12-dummy.netdev',
+        '21-macvlan.netdev',
+        '21-macvtap.netdev',
+        '21-vlan.netdev',
+        '21-vlan.network',
+        '25-6rd-tunnel.netdev',
+        '25-bond.netdev',
+        '25-bridge.netdev',
+        '25-erspan-tunnel.netdev',
+        '25-geneve.netdev',
+        '25-gretap-tunnel.netdev',
+        '25-gre-tunnel.netdev',
+        '25-ip6gre-tunnel.netdev',
+        '25-ip6tnl-tunnel.netdev',
+        '25-ipip-tunnel-independent.netdev',
+        '25-ipip-tunnel.netdev',
+        '25-ipvlan.netdev',
+        '25-isatap-tunnel.netdev',
+        '25-sit-tunnel.netdev',
+        '25-tap.netdev',
+        '25-tun.netdev',
+        '25-vcan.netdev',
+        '25-veth.netdev',
+        '25-vrf.netdev',
+        '25-vti6-tunnel.netdev',
+        '25-vti-tunnel.netdev',
+        '25-vxlan.netdev',
+        '25-wireguard.netdev',
+        '6rd.network',
+        'gre.network',
+        'gretap.network',
+        'gretun.network',
+        'ip6gretap.network',
+        'ip6tnl.network',
+        'ipip.network',
+        'ipvlan.network',
+        'isatap.network',
+        'macvlan.network',
+        'macvtap.network',
+        'sit.network',
+        'vti6.network',
+        'vti.network',
+        'vxlan.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -187,7 +259,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     def test_dropin(self):
         self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('dropin-test'))
@@ -231,12 +302,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     def test_vlan(self):
         self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('vlan99'))
 
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
+        print(output)
         self.assertTrue(output, 'REORDER_HDR')
         self.assertTrue(output, 'LOOSE_BINDING')
         self.assertTrue(output, 'GVRP')
@@ -245,14 +316,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     def test_macvtap(self):
         self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('macvtap99'))
 
     def test_macvlan(self):
         self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('macvlan99'))
@@ -260,35 +329,30 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('ipvlan')
     def test_ipvlan(self):
         self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('ipvlan99'))
 
     def test_veth(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('veth99'))
 
     def test_dummy(self):
         self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('test1'))
 
     def test_tun(self):
         self.copy_unit_to_networkd_unit_path('25-tun.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('tun99'))
 
     def test_tap(self):
         self.copy_unit_to_networkd_unit_path('25-tap.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('tap99'))
@@ -296,7 +360,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('vrf')
     def test_vrf(self):
         self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('vrf99'))
@@ -304,7 +367,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('vcan')
     def test_vcan(self):
         self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('vcan99'))
@@ -312,7 +374,6 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
     @expectedFailureIfModuleIsNotAvailable('wireguard')
     def test_wireguard(self):
         self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
-
         self.start_networkd()
 
         if shutil.which('wg'):
@@ -322,12 +383,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     def test_geneve(self):
         self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('geneve99'))
 
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
+        print(output)
         self.assertTrue(output, '192.168.22.1')
         self.assertTrue(output, '6082')
         self.assertTrue(output, 'udpcsum')
@@ -389,6 +450,17 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('sittun99'))
 
+    def test_isatap_tunnel(self):
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
+        self.start_networkd()
+
+        self.assertTrue(self.link_exits('dummy98'))
+        self.assertTrue(self.link_exits('isataptun99'))
+
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, "isatap ")
+
     def test_6rd_tunnel(self):
         self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
         self.start_networkd()
@@ -410,18 +482,18 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     def test_tunnel_independent(self):
         self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
-
         self.start_networkd()
+
         self.assertTrue(self.link_exits('ipiptun99'))
 
     def test_vxlan(self):
         self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
-
         self.start_networkd()
 
         self.assertTrue(self.link_exits('vxlan99'))
 
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
+        print(output)
         self.assertRegex(output, "999")
         self.assertRegex(output, '5555')
         self.assertRegex(output, 'l2miss')
@@ -434,16 +506,37 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'gbp')
 
 class NetworkdNetWorkTests(unittest.TestCase, Utilities):
-    links = ['dummy98', 'test1', 'bond199']
-
-    units = ['12-dummy.netdev', 'test-static.network', 'configure-without-carrier.network', '11-dummy.netdev',
-             '23-primary-slave.network', '23-test1-bond199.network', '11-dummy.netdev', '23-bond199.network',
-             '25-bond-active-backup-slave.netdev', '12-dummy.netdev', '23-active-slave.network',
-             'routing-policy-rule.network', '25-fibrule-port-range.network', '25-address-section.network',
-             '25-address-section-miscellaneous.network', '25-route-section.network', '25-route-type.network',
-             '25-route-tcp-window-settings.network', '25-route-gateway.network', '25-route-gateway-on-link.network',
-             '25-address-link-section.network', '25-ipv6-address-label-section.network', '25-link-section-unmanaged.network',
-             '25-sysctl.network', '25-route-reverse-order.network']
+    links = [
+        'bond199',
+        'dummy98',
+        'test1']
+
+    units = [
+        '11-dummy.netdev',
+        '12-dummy.netdev',
+        '23-active-slave.network',
+        '23-bond199.network',
+        '23-primary-slave.network',
+        '23-test1-bond199.network',
+        '25-address-link-section.network',
+        '25-address-section-miscellaneous.network',
+        '25-address-section.network',
+        '25-bond-active-backup-slave.netdev',
+        '25-fibrule-invert.network',
+        '25-fibrule-port-range.network',
+        '25-ipv6-address-label-section.network',
+        '25-neighbor-section.network',
+        '25-link-section-unmanaged.network',
+        '25-route-gateway.network',
+        '25-route-gateway-on-link.network',
+        '25-route-reverse-order.network',
+        '25-route-section.network',
+        '25-route-tcp-window-settings.network',
+        '25-route-type.network',
+        '25-sysctl.network',
+        'configure-without-carrier.network',
+        'routing-policy-rule.network',
+        'test-static.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -457,6 +550,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd()
 
         self.assertTrue(self.link_exits('dummy98'))
+
         output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '192.168.0.15')
@@ -468,6 +562,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd()
 
         self.assertTrue(self.link_exits('test1'))
+
         output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '192.168.0.15')
@@ -480,6 +575,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('bond199'))
+
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, 'active_slave dummy98')
@@ -490,6 +586,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('bond199'))
+
         output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, 'primary test1')
@@ -499,6 +596,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.start_networkd()
 
         self.assertTrue(self.link_exits('test1'))
+
         output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '111')
@@ -508,11 +606,14 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'oif test1')
         self.assertRegex(output, 'lookup 7')
 
+        subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
     def test_routing_policy_rule_port_range(self):
         self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
         self.start_networkd()
 
         self.assertTrue(self.link_exits('test1'))
+
         output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '111')
@@ -522,6 +623,23 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'tcp')
         self.assertRegex(output, 'lookup 7')
 
+        subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
+    def test_routing_policy_rule_invert(self):
+        self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
+        self.start_networkd()
+
+        self.assertTrue(self.link_exits('test1'))
+
+        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, '111')
+        self.assertRegex(output, 'not.*?from.*?192.168.100.18')
+        self.assertRegex(output, 'tcp')
+        self.assertRegex(output, 'lookup 7')
+
+        subprocess.call(['ip', 'rule', 'del', 'table', '7'])
+
     def test_address_preferred_lifetime_zero_ipv6(self):
         self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
         self.start_networkd()
@@ -658,6 +776,17 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, '2004:da8:1::/64')
 
+    def test_ipv6_neighbor(self):
+        self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
+        self.start_networkd()
+
+        self.assertTrue(self.link_exits('dummy98'))
+
+        output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
+        print(output)
+        self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
+        self.assertRegex(output, '2004:da8:1:0::1.*00:00:5e:00:02:66.*PERMANENT')
+
     def test_sysctl(self):
         self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
         self.start_networkd()
@@ -672,11 +801,19 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
         self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
 
-class NetworkdNetWorkBrideTests(unittest.TestCase, Utilities):
-    links = ['dummy98', 'test1', 'bridge99']
+class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
+    links = [
+        'bridge99',
+        'dummy98',
+        'test1']
 
-    units = ['11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', '26-bridge-slave-interface-1.network',
-             '26-bridge-slave-interface-2.network', 'bridge99.network']
+    units = [
+        '11-dummy.netdev',
+        '12-dummy.netdev',
+        '26-bridge.netdev',
+        '26-bridge-slave-interface-1.network',
+        '26-bridge-slave-interface-2.network',
+        'bridge99.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -712,15 +849,22 @@ class NetworkdNetWorkBrideTests(unittest.TestCase, Utilities):
 
         output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
         print(output)
-        self.assertRegex(output, 'cost 400')
-        self.assertRegex(output, 'hairpin on')
-        self.assertRegex(output, 'flood on')
-        self.assertRegex(output, 'fastleave on')
+        self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
+        self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
+        self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
+        self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
+
+        # CONFIG_BRIDGE_IGMP_SNOOPING=y
+        if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
+            self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
 
 class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
     links = ['veth99']
 
-    units = ['23-emit-lldp.network', '24-lldp.network', '25-veth.netdev']
+    units = [
+        '23-emit-lldp.network',
+        '24-lldp.network',
+        '25-veth.netdev']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -743,7 +887,10 @@ class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
 class NetworkdNetworkRATests(unittest.TestCase, Utilities):
     links = ['veth99']
 
-    units = ['25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network']
+    units = [
+        '25-veth.netdev',
+        'ipv6-prefix.network',
+        'ipv6-prefix-veth.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -763,10 +910,18 @@ class NetworkdNetworkRATests(unittest.TestCase, Utilities):
         self.assertRegex(output, '2002:da8:1:0')
 
 class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
-    links = ['veth99', 'dummy98']
-
-    units = ['25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network', '12-dummy.netdev', '24-search-domain.network',
-             'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network']
+    links = [
+        'dummy98',
+        'veth99']
+
+    units = [
+        '12-dummy.netdev',
+        '24-search-domain.network',
+        '25-veth.netdev',
+        'dhcp-client.network',
+        'dhcp-client-timezone-router.network',
+        'dhcp-server.network',
+        'dhcp-server-timezone-router.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -781,8 +936,6 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        time.sleep(5)
-
         output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '192.168.5.*')
@@ -815,14 +968,24 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'Europe/Berlin')
 
 class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
-    links = ['veth99', 'dummy98']
-
-    units = ['25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network',
-             'dhcp-client-ipv4-only-ipv6-disabled.network', 'dhcp-client-ipv4-only.network',
-             'dhcp-client-ipv4-dhcp-settings.network', 'dhcp-client-anonymize.network',
-             'dhcp-client-ipv6-rapid-commit.network', 'dhcp-client-route-table.network',
-             'dhcp-v4-server-veth-peer.network', 'dhcp-client-listen-port.network',
-             'dhcp-client-route-metric.network', 'dhcp-client-critical-connection.network']
+    links = [
+        'dummy98',
+        'veth99']
+
+    units = [
+        '25-veth.netdev',
+        'dhcp-client-anonymize.network',
+        'dhcp-client-critical-connection.network',
+        'dhcp-client-ipv4-dhcp-settings.network',
+        'dhcp-client-ipv4-only-ipv6-disabled.network',
+        'dhcp-client-ipv4-only.network',
+        'dhcp-client-ipv6-only.network',
+        'dhcp-client-ipv6-rapid-commit.network',
+        'dhcp-client-listen-port.network',
+        'dhcp-client-route-metric.network',
+        'dhcp-client-route-table.network',
+        'dhcp-server-veth-peer.network',
+        'dhcp-v4-server-veth-peer.network']
 
     def setUp(self):
         self.link_remove(self.links)
@@ -893,10 +1056,10 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         print(output)
         self.assertRegex(output, 'default.*dev veth99 proto dhcp')
 
-        self.search_words_in_file('vendor class: SusantVendorTest')
-        self.search_words_in_file('client MAC address: 12:34:56:78:9a:bc')
-        self.search_words_in_file('client provides name: test-hostname')
-        self.search_words_in_file('26:mtu')
+        self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
+        self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
+        self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
+        self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
 
     def test_dhcp6_client_settings_rapidcommit_true(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
@@ -909,8 +1072,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
-
-        self.assertTrue(self.search_words_in_file('14:rapid-commit'))
+        self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
 
     def test_dhcp6_client_settings_rapidcommit_false(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
@@ -923,8 +1085,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
-
-        self.assertFalse(self.search_words_in_file('14:rapid-commit'))
+        self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
 
     def test_dhcp_client_settings_anonymize(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
@@ -933,12 +1094,14 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('veth99'))
 
         self.start_dnsmasq()
-        self.assertFalse(self.search_words_in_file('VendorClassIdentifier=SusantVendorTest'))
-        self.assertFalse(self.search_words_in_file('test-hostname'))
-        self.assertFalse(self.search_words_in_file('26:mtu'))
+
+        self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
+        self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
+        self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
 
     def test_dhcp_client_listen_port(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
+
         dh_server = DHCPServer("dhcp_server")
         dh_server.start()
 
@@ -957,39 +1120,40 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
     def test_dhcp_route_table_id(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
         self.start_networkd()
-        self.start_dnsmasq()
 
         self.assertTrue(self.link_exits('veth99'))
 
+        self.start_dnsmasq()
+
         output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
         print(output)
-
         self.assertRegex(output, 'veth99 proto dhcp')
         self.assertRegex(output, '192.168.5.1')
 
     def test_dhcp_route_metric(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
         self.start_networkd()
-        self.start_dnsmasq()
 
         self.assertTrue(self.link_exits('veth99'))
 
+        self.start_dnsmasq()
+
         output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
         print(output)
-
         self.assertRegex(output, 'metric 24')
 
     def test_dhcp_route_criticalconnection_true(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
         self.start_networkd()
-        self.start_dnsmasq()
 
         self.assertTrue(self.link_exits('veth99'))
 
+        self.start_dnsmasq()
+
         output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
         print(output)
-
         self.assertRegex(output, '192.168.5.*')
+
         # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
         self.stop_dnsmasq(dnsmasq_pid_file)
 
index b65869d02b6cd1d0b14dffe70828e270b9047aee..ca1e13df9a9894540a08e0f1e27ac7e74d09eeaa 100755 (executable)
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 # SPDX-License-Identifier: MIT
 #
 # This file is distributed under the MIT license, see below.
index ea151601075adc234f89fb199fe7f3e89234de1b..4e8593f320099b96c568baee3eff57ad762f0e77 100644 (file)
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 # SPDX-License-Identifier: LGPL-2.1+
 
 from __future__ import print_function
@@ -16,7 +15,6 @@ class sd_dump_hashmaps(gdb.Command):
                 d = gdb.parse_and_eval("hashmap_debug_list")
                 all_entry_sizes = gdb.parse_and_eval("all_entry_sizes")
                 all_direct_buckets = gdb.parse_and_eval("all_direct_buckets")
-                hashmap_base_t = gdb.lookup_type("HashmapBase")
                 uchar_t = gdb.lookup_type("unsigned char")
                 ulong_t = gdb.lookup_type("unsigned long")
                 debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug")
index aca9ab1fe91e3123ac3a99355efb699d715283de..5392df0ebbbb2105f3cac4f9fc183949e0b24c07 100755 (executable)
@@ -1,6 +1,8 @@
 #!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1+
 
-"""Generate %-from-name.gperf from %-list.txt
+"""
+Generate %-from-name.gperf from %-list.txt
 """
 
 import sys
index 8b85ef40f3ec2987e7ec99257a0e8ce8d038560a..8703c8a37bd073f6938f706bb36f8f12b4261749 100755 (executable)
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 # SPDX-License-Identifier: LGPL-2.1+
 
 import sys
index 7ed98cb4e006bf84caa0ad424bbba50b16853b2f..66027af02e526ad4e1a45fd4097fbbb8a7c7867d 100755 (executable)
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
 # SPDX-License-Identifier: LGPL-2.1+
 
 import collections
index 42a48bc98ccaeab367d377dd1f83e11a1fd9801b..c4551c6f61d000fff9dce3c7be0fa162c57fee97 100755 (executable)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python3
-#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#  SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
 
 from __future__ import print_function
 import collections
index 19e343b4e3a36b20e5f27f41155c332a34817eae..f399e7493ca2461647a3ccf2f76002376dd5d8ab 100755 (executable)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python3
-#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
-#  SPDX-License-Identifier: LGPL-2.1+
+# SPDX-License-Identifier: LGPL-2.1+
 
 from lxml import etree as tree
 
diff --git a/travis-ci/managers/debian.sh b/travis-ci/managers/debian.sh
new file mode 100755 (executable)
index 0000000..af2f0da
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Run this script from the root of the systemd's git repository
+# or set REPO_ROOT to a correct path.
+#
+# Example execution on Fedora:
+# dnf install docker
+# systemctl start docker
+# export CONT_NAME="my-fancy-container"
+# travis-ci/managers/debian.sh SETUP RUN CLEANUP
+
+PHASES=(${@:-SETUP RUN RUN_ASAN CLEANUP})
+DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
+CONT_NAME="${CONT_NAME:-debian-$DEBIAN_RELEASE-$RANDOM}"
+DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
+DOCKER_RUN="${DOCKER_RUN:-docker run}"
+REPO_ROOT="${REPO_ROOT:-$PWD}"
+ADDITIONAL_DEPS=(python3-libevdev python3-pyparsing clang)
+
+function info() {
+    echo -e "\033[33;1m$1\033[0m"
+}
+
+set -e
+
+source "$(dirname $0)/travis_wait.bash"
+
+for phase in "${PHASES[@]}"; do
+    case $phase in
+        SETUP)
+            info "Setup phase"
+            info "Using Debian $DEBIAN_RELEASE"
+            printf "FROM debian:$DEBIAN_RELEASE\nRUN bash -c 'apt-get -y update && apt-get install -y systemd'\n" | docker build -t debian-with-systemd/latest -
+            info "Starting container $CONT_NAME"
+            $DOCKER_RUN -v $REPO_ROOT:/build:rw \
+                        -w /build --privileged=true --name $CONT_NAME \
+                        -dit --net=host debian-with-systemd/latest /usr/bin/systemd
+            $DOCKER_EXEC bash -c "echo deb-src http://deb.debian.org/debian $DEBIAN_RELEASE main >>/etc/apt/sources.list"
+            $DOCKER_EXEC apt-get -y update
+            $DOCKER_EXEC apt-get -y build-dep systemd
+            $DOCKER_EXEC apt-get -y install "${ADDITIONAL_DEPS[@]}"
+            # overlayfs on TravisCI is having trouble delivering inotify events to test-path and test-event.
+            # Let's use tmpfs instead for now.
+            $DOCKER_EXEC mount -t tmpfs tmpfs /tmp
+            ;;
+        RUN)
+            info "Run phase"
+            $DOCKER_EXEC meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true build
+            $DOCKER_EXEC ninja -v -C build
+            $DOCKER_EXEC ninja -C build test
+            $DOCKER_EXEC tools/check-directives.sh
+            ;;
+        RUN_CLANG)
+            docker exec -e CC=clang -e CXX=clang++ -it $CONT_NAME meson --werror -Dtests=unsafe -Dslow-tests=true -Dsplit-usr=true build
+            $DOCKER_EXEC ninja -v -C build
+            $DOCKER_EXEC ninja -C build test
+            ;;
+        RUN_ASAN|RUN_CLANG_ASAN)
+            if [[ "$phase" = "RUN_CLANG_ASAN" ]]; then
+                ENV_VARS="-e CC=clang -e CXX=clang++"
+                MESON_ARGS="-Db_lundef=false" # See https://github.com/mesonbuild/meson/issues/764
+            fi
+            docker exec $ENV_VARS -it $CONT_NAME meson --werror -Dtests=unsafe -Db_sanitize=address,undefined -Dsplit-usr=true $MESON_ARGS build
+            $DOCKER_EXEC ninja -v -C build
+
+            # Never remove halt_on_error from UBSAN_OPTIONS. See https://github.com/systemd/systemd/commit/2614d83aa06592aedb.
+            travis_wait docker exec --interactive=false \
+                -e UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 \
+                -e ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 \
+                -e "TRAVIS=$TRAVIS" \
+                -t $CONT_NAME \
+                meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs
+            ;;
+        CLEANUP)
+            info "Cleanup phase"
+            docker stop $CONT_NAME
+            docker rm -f $CONT_NAME
+            ;;
+        *)
+            echo >&2 "Unknown phase '$phase'"
+            exit 1
+    esac
+done