summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile-man.am52
-rw-r--r--Makefile.am4
-rw-r--r--hwdb/60-evdev.hwdb14
-rwxr-xr-xhwdb/acpi-update.py2
-rwxr-xr-xhwdb/parse_hwdb.py2
-rwxr-xr-xman/90-rearrange-path.py2
-rw-r--r--man/environment.d.xml3
-rw-r--r--man/meson.build46
-rw-r--r--man/rules/meson.build15
-rw-r--r--man/systemd-environment-d-generator.xml2
-rw-r--r--man/systemd-hibernate-resume-generator.xml2
-rw-r--r--man/systemd-hibernate-resume@.service.xml2
-rw-r--r--man/systemd-resolve.xml2
-rw-r--r--man/systemd.environment-generator.xml3
-rw-r--r--man/systemd.netdev.xml11
-rw-r--r--man/systemd.network.xml27
-rw-r--r--man/systemd.unit.xml19
-rw-r--r--src/basic/dirent-util.c11
-rw-r--r--src/basic/dirent-util.h2
-rw-r--r--src/basic/extract-word.c7
-rw-r--r--src/basic/extract-word.h2
-rw-r--r--src/basic/generate-gperfs.py2
-rw-r--r--src/basic/glob-util.c64
-rw-r--r--src/basic/glob-util.h4
-rw-r--r--src/basic/rm-rf.c9
-rw-r--r--src/boot/efi/measure.c6
-rw-r--r--src/boot/efi/measure.h5
-rw-r--r--src/cgtop/cgtop.c20
-rw-r--r--src/core/dbus-unit.c1
-rw-r--r--src/core/device.c2
-rw-r--r--src/core/execute.c21
-rw-r--r--src/core/job.c38
-rw-r--r--src/core/job.h2
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/service.c3
-rw-r--r--src/core/transaction.c2
-rw-r--r--src/core/unit.c4
-rw-r--r--src/core/unit.h1
-rw-r--r--src/fstab-generator/fstab-generator.c4
-rw-r--r--src/import/pull-common.c1
-rw-r--r--src/import/pull-raw.c1
-rwxr-xr-xsrc/journal-remote/log-generator.py2
-rw-r--r--src/journal/journal-file.c3
-rw-r--r--src/libsystemd-network/network-internal.c39
-rw-r--r--src/libsystemd-network/network-internal.h7
-rw-r--r--src/libsystemd-network/sd-ndisc.c1
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c44
-rw-r--r--src/libsystemd/sd-netlink/netlink-util.h4
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c40
-rw-r--r--src/network/meson.build2
-rw-r--r--src/network/netdev/geneve.c30
-rw-r--r--src/network/netdev/geneve.h12
-rw-r--r--src/network/netdev/netdev-gperf.gperf4
-rw-r--r--src/network/netdev/netdev.c8
-rw-r--r--src/network/netdev/vxlan.c30
-rw-r--r--src/network/netdev/vxlan.h11
-rw-r--r--src/network/networkd-address-label.c257
-rw-r--r--src/network/networkd-address-label.h59
-rw-r--r--src/network/networkd-link.c45
-rw-r--r--src/network/networkd-link.h5
-rw-r--r--src/network/networkd-network-gperf.gperf4
-rw-r--r--src/network/networkd-network.c11
-rw-r--r--src/network/networkd-network.h4
-rw-r--r--src/nspawn/nspawn.c8
-rw-r--r--src/resolve/generate-dns_type-gperf.py2
-rw-r--r--src/shared/conf-parser.c37
-rw-r--r--src/shared/conf-parser.h1
-rw-r--r--src/shared/efivars.c1
-rw-r--r--src/shared/generator.c41
-rw-r--r--src/shared/generator.h6
-rw-r--r--src/shared/meson.build2
-rw-r--r--src/systemd/sd-netlink.h3
-rw-r--r--src/test/generate-sym-test.py2
-rw-r--r--src/test/test-glob-util.c66
-rw-r--r--src/test/test-path-util.c34
-rw-r--r--src/test/test-sizeof.c11
-rw-r--r--src/tmpfiles/tmpfiles.c11
-rw-r--r--test/README.testsuite2
-rwxr-xr-xtest/create-sys-script.py4
-rwxr-xr-xtest/rule-syntax-check.py2
-rwxr-xr-xtest/sys-script.py2
-rwxr-xr-xtest/sysv-generator-test.py2
-rwxr-xr-xtest/test-exec-deserialization.py2
-rw-r--r--tools/catalog-report.py2
-rw-r--r--tools/gdb-sd_dump_hashmaps.py2
-rwxr-xr-xtools/make-directive-index.py2
-rwxr-xr-xtools/make-man-index.py2
-rw-r--r--tools/make-man-rules.py2
-rw-r--r--tools/xml_helper.py2
89 files changed, 1031 insertions, 263 deletions
diff --git a/Makefile-man.am b/Makefile-man.am
index f436361074..f21cc527f0 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -11,7 +11,6 @@ MANPAGES += \
man/bootup.7 \
man/busctl.1 \
man/daemon.7 \
- man/environment.d.5 \
man/file-hierarchy.7 \
man/halt.8 \
man/hostname.5 \
@@ -111,15 +110,12 @@ MANPAGES += \
man/systemd-debug-generator.8 \
man/systemd-delta.1 \
man/systemd-detect-virt.1 \
- man/systemd-environment-d-generator.8 \
man/systemd-escape.1 \
man/systemd-fsck@.service.8 \
man/systemd-fstab-generator.8 \
man/systemd-getty-generator.8 \
man/systemd-gpt-auto-generator.8 \
man/systemd-halt.service.8 \
- man/systemd-hibernate-resume-generator.8 \
- man/systemd-hibernate-resume@.service.8 \
man/systemd-inhibit.1 \
man/systemd-initctl.service.8 \
man/systemd-journald.service.8 \
@@ -130,7 +126,6 @@ MANPAGES += \
man/systemd-nspawn.1 \
man/systemd-path.1 \
man/systemd-remount-fs.service.8 \
- man/systemd-resolve.1 \
man/systemd-run.1 \
man/systemd-sleep.conf.5 \
man/systemd-socket-activate.1 \
@@ -148,7 +143,6 @@ MANPAGES += \
man/systemd.1 \
man/systemd.automount.5 \
man/systemd.device.5 \
- man/systemd.environment-generator.7 \
man/systemd.exec.5 \
man/systemd.generator.7 \
man/systemd.journal-fields.7 \
@@ -187,7 +181,6 @@ MANPAGES += \
man/udev_new.3 \
man/udevadm.8
MANPAGES_ALIAS += \
- man/30-systemd-environment-d-generator.8 \
man/SD_ALERT.3 \
man/SD_BUS_ERROR_ACCESS_DENIED.3 \
man/SD_BUS_ERROR_ADDRESS_IN_USE.3 \
@@ -463,7 +456,6 @@ MANPAGES_ALIAS += \
man/systemd-ask-password-wall.service.8 \
man/systemd-fsck-root.service.8 \
man/systemd-fsck.8 \
- man/systemd-hibernate-resume.8 \
man/systemd-hibernate.service.8 \
man/systemd-hybrid-sleep.service.8 \
man/systemd-initctl.8 \
@@ -547,7 +539,6 @@ MANPAGES_ALIAS += \
man/udev_ref.3 \
man/udev_unref.3 \
man/user.conf.d.5
-man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8
man/SD_ALERT.3: man/sd-daemon.3
man/SD_BUS_ERROR_ACCESS_DENIED.3: man/sd-bus-errors.3
man/SD_BUS_ERROR_ADDRESS_IN_USE.3: man/sd-bus-errors.3
@@ -823,7 +814,6 @@ man/systemd-ask-password-wall.path.8: man/systemd-ask-password-console.service.8
man/systemd-ask-password-wall.service.8: man/systemd-ask-password-console.service.8
man/systemd-fsck-root.service.8: man/systemd-fsck@.service.8
man/systemd-fsck.8: man/systemd-fsck@.service.8
-man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
man/systemd-hibernate.service.8: man/systemd-suspend.service.8
man/systemd-hybrid-sleep.service.8: man/systemd-suspend.service.8
man/systemd-initctl.8: man/systemd-initctl.service.8
@@ -907,9 +897,6 @@ man/udev_monitor_unref.3: man/udev_monitor_new_from_netlink.3
man/udev_ref.3: man/udev_new.3
man/udev_unref.3: man/udev_new.3
man/user.conf.d.5: man/systemd-system.conf.5
-man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html
- $(html-alias)
-
man/SD_ALERT.html: man/sd-daemon.html
$(html-alias)
@@ -1735,9 +1722,6 @@ man/systemd-fsck-root.service.html: man/systemd-fsck@.service.html
man/systemd-fsck.html: man/systemd-fsck@.service.html
$(html-alias)
-man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html
- $(html-alias)
-
man/systemd-hibernate.service.html: man/systemd-suspend.service.html
$(html-alias)
@@ -2043,6 +2027,19 @@ MANPAGES_ALIAS += \
endif
+if ENABLE_ENVIRONMENT_D
+MANPAGES += \
+ man/environment.d.5 \
+ man/systemd-environment-d-generator.8 \
+ man/systemd.environment-generator.7
+MANPAGES_ALIAS += \
+ man/30-systemd-environment-d-generator.8
+man/30-systemd-environment-d-generator.8: man/systemd-environment-d-generator.8
+man/30-systemd-environment-d-generator.html: man/systemd-environment-d-generator.html
+ $(html-alias)
+
+endif
+
if ENABLE_FIRSTBOOT
MANPAGES += \
man/systemd-firstboot.1
@@ -2054,6 +2051,18 @@ man/systemd-firstboot.service.html: man/systemd-firstboot.html
endif
+if ENABLE_HIBERNATE
+MANPAGES += \
+ man/systemd-hibernate-resume-generator.8 \
+ man/systemd-hibernate-resume@.service.8
+MANPAGES_ALIAS += \
+ man/systemd-hibernate-resume.8
+man/systemd-hibernate-resume.8: man/systemd-hibernate-resume@.service.8
+man/systemd-hibernate-resume.html: man/systemd-hibernate-resume@.service.html
+ $(html-alias)
+
+endif
+
if ENABLE_HOSTNAMED
MANPAGES += \
man/hostnamectl.1 \
@@ -2188,6 +2197,7 @@ MANPAGES += \
man/dnssec-trust-anchors.d.5 \
man/nss-resolve.8 \
man/resolved.conf.5 \
+ man/systemd-resolve.1 \
man/systemd-resolved.service.8
MANPAGES_ALIAS += \
man/libnss_resolve.so.2.8 \
@@ -2605,6 +2615,16 @@ man/systemd-user-sessions.html: man/systemd-user-sessions.service.html
endif
+if HAVE_PYTHON
+MANPAGES += \
+ man/systemd.directives.7 \
+ man/systemd.index.7
+MANPAGES_ALIAS += \
+ #
+
+
+endif
+
if HAVE_SYSV_COMPAT
MANPAGES += \
man/systemd-sysv-generator.8
diff --git a/Makefile.am b/Makefile.am
index f5f2793f5b..d565978266 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -749,9 +749,11 @@ man/index.html: man/systemd.index.html
$(AM_V_LN)$(LN_S) -f systemd.index.html $@
if HAVE_PYTHON
+if ENABLE_MANPAGES
noinst_DATA += \
man/index.html
endif
+endif
CLEANFILES += \
man/index.html
@@ -5812,6 +5814,8 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-network-bus.c \
src/network/networkd-address.h \
src/network/networkd-address.c \
+ src/network/networkd-address-label.h \
+ src/network/networkd-address-label.c \
src/network/networkd-route.h \
src/network/networkd-route.c \
src/network/networkd-fdb.h \
diff --git a/hwdb/60-evdev.hwdb b/hwdb/60-evdev.hwdb
index 5b7d31ace1..d3b920bb99 100644
--- a/hwdb/60-evdev.hwdb
+++ b/hwdb/60-evdev.hwdb
@@ -115,6 +115,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pn?550C?:*
EVDEV_ABS_35=::31
EVDEV_ABS_36=::30
+# Asus UX301L
+evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX301LAA:*
+ EVDEV_ABS_00=::30
+ EVDEV_ABS_01=::29
+ EVDEV_ABS_35=::30
+ EVDEV_ABS_36=::29
+
# Asus UX305
evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX305UA:*
EVDEV_ABS_00=0:3097:32
@@ -338,6 +345,13 @@ evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/
EVDEV_ABS_35=0:2480:28
EVDEV_ABS_36=0:1116:24
+# Samsung 880Z5E
+evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E*
+ EVDEV_ABS_00=::30
+ EVDEV_ABS_01=::29
+ EVDEV_ABS_35=::30
+ EVDEV_ABS_36=::29
+
#########################################
# Toshiba
#########################################
diff --git a/hwdb/acpi-update.py b/hwdb/acpi-update.py
index 50da531dc6..2c23b057fb 100755
--- a/hwdb/acpi-update.py
+++ b/hwdb/acpi-update.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
from html.parser import HTMLParser
from enum import Enum
diff --git a/hwdb/parse_hwdb.py b/hwdb/parse_hwdb.py
index e2c65c4be0..adf8a1963e 100755
--- a/hwdb/parse_hwdb.py
+++ b/hwdb/parse_hwdb.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd. It is distrubuted under the MIT license, see
diff --git a/man/90-rearrange-path.py b/man/90-rearrange-path.py
index c6ff32210f..7537d5e915 100755
--- a/man/90-rearrange-path.py
+++ b/man/90-rearrange-path.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
"""
diff --git a/man/environment.d.xml b/man/environment.d.xml
index be7758a2f9..78b949160b 100644
--- a/man/environment.d.xml
+++ b/man/environment.d.xml
@@ -20,7 +20,8 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="environment.d" xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="environment.d" conditional='ENABLE_ENVIRONMENT_D'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>environment.d</title>
diff --git a/man/meson.build b/man/meson.build
index 6f7b1e8793..4f2ddad31a 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -61,15 +61,32 @@ foreach tuple : manpages
install_dir : mandirn)
man_pages += [p1]
- p2 = custom_target(
+ p2 = []
+ foreach htmlalias : htmlaliases
+ link = custom_target(
+ htmlalias,
+ input : p2,
+ output : htmlalias,
+ command : ['ln', '-fs', html, '@OUTPUT@'])
+ if want_html
+ dst = join_paths(docdir, 'html', htmlalias)
+ cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+ meson.add_install_script('sh', '-c', cmd)
+ p2 += [link]
+ endif
+ html_pages += [link]
+ endforeach
+
+ p3 = custom_target(
html,
input : xml,
- output : [html] + htmlaliases,
+ output : html,
command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
depend_files : custom_entities_ent,
+ depends : p2,
install : want_html,
install_dir : join_paths(docdir, 'html'))
- html_pages += [p2]
+ html_pages += [p3]
source_xml_files += files(tuple[0] + '.xml')
else
@@ -117,14 +134,33 @@ foreach tuple : [['systemd.directives', '7', systemd_directives_xml],
install_dir : mandirn)
man_pages += [p1]
- p2 = custom_target(
+ p2 = []
+ if html == 'systemd.index.html'
+ htmlalias = 'index.html'
+ link = custom_target(
+ htmlalias,
+ input : p2,
+ output : htmlalias,
+ command : ['ln', '-fs', html, '@OUTPUT@'])
+ if want_html
+ dst = join_paths(docdir, 'html', htmlalias)
+ cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst)
+ meson.add_install_script('sh', '-c', cmd)
+ p2 += [link]
+ endif
+ html_pages += [link]
+ endif
+
+ p3 = custom_target(
html,
input : xml,
output : html,
command : xslt_cmd + [custom_html_xsl, '@INPUT@'],
+ depend_files : custom_entities_ent,
+ depends : p2,
install : want_html and have_lxml,
install_dir : join_paths(docdir, 'html'))
- html_pages += [p2]
+ html_pages += [p3]
endforeach
# cannot use run_target until https://github.com/mesonbuild/meson/issues/1644 is resolved
diff --git a/man/rules/meson.build b/man/rules/meson.build
index 21c996f9b4..1508b012df 100644
--- a/man/rules/meson.build
+++ b/man/rules/meson.build
@@ -12,7 +12,7 @@ manpages = [
'5',
['systemd.negative', 'systemd.positive'],
'ENABLE_RESOLVED'],
- ['environment.d', '5', [], ''],
+ ['environment.d', '5', [], 'ENABLE_ENVIRONMENT_D'],
['file-hierarchy', '7', [], ''],
['halt', '8', ['poweroff', 'reboot'], ''],
['hostname', '5', [], ''],
@@ -521,7 +521,7 @@ manpages = [
['systemd-environment-d-generator',
'8',
['30-systemd-environment-d-generator'],
- ''],
+ 'ENABLE_ENVIRONMENT_D'],
['systemd-escape', '1', [], ''],
['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'],
['systemd-fsck@.service',
@@ -538,8 +538,11 @@ manpages = [
'systemd-reboot.service',
'systemd-shutdown'],
''],
- ['systemd-hibernate-resume-generator', '8', [], ''],
- ['systemd-hibernate-resume@.service', '8', ['systemd-hibernate-resume'], ''],
+ ['systemd-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'],
+ ['systemd-hibernate-resume@.service',
+ '8',
+ ['systemd-hibernate-resume'],
+ 'ENABLE_HIBERNATE'],
['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'],
['systemd-hwdb', '8', [], 'ENABLE_HWDB'],
['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'],
@@ -585,7 +588,7 @@ manpages = [
['systemd-random-seed'],
'ENABLE_RANDOMSEED'],
['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
- ['systemd-resolve', '1', [], ''],
+ ['systemd-resolve', '1', [], 'ENABLE_RESOLVED'],
['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVED'],
['systemd-rfkill.service',
'8',
@@ -644,7 +647,7 @@ manpages = [
['systemd', '1', ['init'], ''],
['systemd.automount', '5', [], ''],
['systemd.device', '5', [], ''],
- ['systemd.environment-generator', '7', [], ''],
+ ['systemd.environment-generator', '7', [], 'ENABLE_ENVIRONMENT_D'],
['systemd.exec', '5', [], ''],
['systemd.generator', '7', [], ''],
['systemd.journal-fields', '7', [], ''],
diff --git a/man/systemd-environment-d-generator.xml b/man/systemd-environment-d-generator.xml
index cc00a5256d..7950aa98a5 100644
--- a/man/systemd-environment-d-generator.xml
+++ b/man/systemd-environment-d-generator.xml
@@ -23,7 +23,7 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-environment-d-generator">
+<refentry id="systemd-environment-d-generator" conditional='ENABLE_ENVIRONMENT_D'>
<refentryinfo>
<title>systemd-environment-d-generator</title>
diff --git a/man/systemd-hibernate-resume-generator.xml b/man/systemd-hibernate-resume-generator.xml
index d811b9b551..3bbb6ab989 100644
--- a/man/systemd-hibernate-resume-generator.xml
+++ b/man/systemd-hibernate-resume-generator.xml
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-hibernate-resume-generator">
+<refentry id="systemd-hibernate-resume-generator" conditional='ENABLE_HIBERNATE'>
<refentryinfo>
<title>systemd-hibernate-resume-generator</title>
diff --git a/man/systemd-hibernate-resume@.service.xml b/man/systemd-hibernate-resume@.service.xml
index 7d00827447..a968adf0a9 100644
--- a/man/systemd-hibernate-resume@.service.xml
+++ b/man/systemd-hibernate-resume@.service.xml
@@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-hibernate-resume@.service">
+<refentry id="systemd-hibernate-resume@.service" conditional='ENABLE_HIBERNATE'>
<refentryinfo>
<title>systemd-hibernate-resume@.service</title>
diff --git a/man/systemd-resolve.xml b/man/systemd-resolve.xml
index 50da971b07..e3ef26bb81 100644
--- a/man/systemd-resolve.xml
+++ b/man/systemd-resolve.xml
@@ -21,7 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd-resolve"
+<refentry id="systemd-resolve" conditional='ENABLE_RESOLVED'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
diff --git a/man/systemd.environment-generator.xml b/man/systemd.environment-generator.xml
index fedbd60175..ff8be92833 100644
--- a/man/systemd.environment-generator.xml
+++ b/man/systemd.environment-generator.xml
@@ -24,7 +24,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
-<refentry id="systemd.environment-generator" xmlns:xi="http://www.w3.org/2001/XInclude">
+<refentry id="systemd.environment-generator" conditional='ENABLE_ENVIRONMENT_D'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd.environment-generator</title>
<productname>systemd</productname>
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index cb2bd23f71..f9b558520b 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -600,8 +600,8 @@
<listitem>
<para>Configures the default destination UDP port on a per-device basis.
If destination port is not specified then Linux kernel default will be used.
- Set destination port 4789 to get the IANA assigned value,
- and destination port 0 to get default values.</para>
+ Set destination port 4789 to get the IANA assigned value. If not set or if the
+ destination port is assigned the empty string the default port of 4789 is used.</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -646,13 +646,13 @@
<varlistentry>
<term><varname>TOS=</varname></term>
<listitem>
- <para>Specifies the TOS value to use in outgoing packets. Ranges [1-255]. </para>
+ <para>Specifies the TOS value to use in outgoing packets. Ranges [1-255].</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TTL=</varname></term>
<listitem>
- <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255]. </para>
+ <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255].</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -676,7 +676,8 @@
<varlistentry>
<term><varname>DestinationPort=</varname></term>
<listitem>
- <para>Specifies destination port. Defaults to 6081.</para>
+ <para>Specifies destination port. Defaults to 6081. If not set or assigned the empty string, the default
+ port of 6081 is used.</para>
</listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 4b80578333..ad0e0cf48a 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -796,6 +796,33 @@
</variablelist>
</refsect1>
+ <refsect1>
+ <title>[IPv6AddressLabel] Section Options</title>
+
+ <para>An <literal>[IPv6AddressLabel]</literal> section accepts the
+ following keys. Specify several <literal>[IPv6AddressLabel]</literal>
+ sections to configure several addresse labels. IPv6 address labels are
+ used for address selection. See <ulink url="https://tools.ietf.org/html/rfc3484">RFC 3484</ulink>.
+ Precedence is managed by userspace, and only the label itself is stored in the kernel</para>
+
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>Label=</varname></term>
+ <listitem>
+ <para> The label for the prefix (an unsigned integer) ranges 0 to 4294967294.
+ 0xffffffff is reserved. This key is mandatory.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>Prefix=</varname></term>
+ <listitem>
+ <para>IPv6 prefix is an address with a prefix length, separated by a slash <literal>/</literal> character.
+ This key is mandatory. </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>[Route] Section Options</title>
<para>The <literal>[Route]</literal> section accepts the
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 68bf0b2407..a7c37a0018 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -718,17 +718,20 @@
<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 may be configured. If this time limit is
- reached, the job will be cancelled, the unit however will not change state or even enter the
- <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts disabled),
- except for device units. NB: this timeout is independent from any unit-specific timeout (for example, the
- timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has 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><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
+ started. If either time limit is reached, the job will be cancelled, the unit however will not change state or
+ even enter the <literal>failed</literal> mode. This value defaults to <literal>infinity</literal> (job timeouts
+ disabled), except for device units (<varname>JobRunningTimeoutSec=</varname> defaults to
+ <varname>DefaultTimeoutStartSec=</varname>). NB: this timeout is independent from any unit-specific timeout
+ (for example, the timeout set with <varname>TimeoutStartSec=</varname> in service units) as the job timeout has
+ 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>
<para><varname>JobTimeoutAction=</varname>
optionally configures an additional
diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c
index 6b9d26773e..5bf58bcdc3 100644
--- a/src/basic/dirent-util.c
+++ b/src/basic/dirent-util.c
@@ -75,3 +75,14 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
return endswith(de->d_name, suffix);
}
+
+struct dirent* readdir_no_dot(DIR *dirp) {
+ struct dirent* d;
+
+ for (;;) {
+ d = readdir(dirp);
+ if (d && dot_or_dot_dot(d->d_name))
+ continue;
+ return d;
+ }
+}
diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h
index b91d04908f..18b9db9b28 100644
--- a/src/basic/dirent-util.h
+++ b/src/basic/dirent-util.h
@@ -31,6 +31,8 @@ int dirent_ensure_type(DIR *d, struct dirent *de);
bool dirent_is_file(const struct dirent *de) _pure_;
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;
+struct dirent* readdir_no_dot(DIR *dirp);
+
#define FOREACH_DIRENT(de, d, on_error) \
for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \
if (!de) { \
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index f8cac3e911..804f14c44c 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -241,7 +241,12 @@ int extract_first_word_and_warn(
return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
}
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
+/* We pass ExtractFlags as unsigned int (to avoid undefined behaviour when passing
+ * an object that undergoes default argument promotion as an argument to va_start).
+ * Let's make sure that ExtractFlags fits into an unsigned int. */
+assert_cc(sizeof(enum ExtractFlags) <= sizeof(unsigned));
+
+int extract_many_words(const char **p, const char *separators, unsigned flags, ...) {
va_list ap;
char **l;
int n = 0, i, c, r;
diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h
index 21db5ef33f..04746c6d08 100644
--- a/src/basic/extract-word.h
+++ b/src/basic/extract-word.h
@@ -32,4 +32,4 @@ typedef enum ExtractFlags {
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
-int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
+int extract_many_words(const char **p, const char *separators, unsigned flags, ...) _sentinel_;
diff --git a/src/basic/generate-gperfs.py b/src/basic/generate-gperfs.py
index 2e7d8931dd..d4cc9aa45c 100644
--- a/src/basic/generate-gperfs.py
+++ b/src/basic/generate-gperfs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
"""Generate %-from-name.gperf from %-list.txt
"""
diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c
index 007198c269..f611c42e4c 100644
--- a/src/basic/glob-util.c
+++ b/src/basic/glob-util.c
@@ -17,54 +17,70 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
#include <errno.h>
#include <glob.h>
+#include <sys/types.h>
+#include "dirent-util.h"
#include "glob-util.h"
#include "macro.h"
+#include "path-util.h"
#include "strv.h"
-int glob_exists(const char *path) {
- _cleanup_globfree_ glob_t g = {};
+int safe_glob(const char *path, int flags, glob_t *pglob) {
int k;
- assert(path);
+ /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */
+ assert(!(flags & GLOB_ALTDIRFUNC));
+
+ if (!pglob->gl_closedir)
+ pglob->gl_closedir = (void (*)(void *)) closedir;
+ if (!pglob->gl_readdir)
+ pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot;
+ if (!pglob->gl_opendir)
+ pglob->gl_opendir = (void *(*)(const char *)) opendir;
+ if (!pglob->gl_lstat)
+ pglob->gl_lstat = lstat;
+ if (!pglob->gl_stat)
+ pglob->gl_stat = stat;
errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+ k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob);
if (k == GLOB_NOMATCH)
- return 0;
+ return -ENOENT;
if (k == GLOB_NOSPACE)
return -ENOMEM;
if (k != 0)
return errno > 0 ? -errno : -EIO;
+ if (strv_isempty(pglob->gl_pathv))
+ return -ENOENT;
- return !strv_isempty(g.gl_pathv);
+ return 0;
}
-int glob_extend(char ***strv, const char *path) {
+int glob_exists(const char *path) {
_cleanup_globfree_ glob_t g = {};
int k;
- char **p;
- errno = 0;
- k = glob(path, GLOB_NOSORT|GLOB_BRACE, NULL, &g);
+ assert(path);
- if (k == GLOB_NOMATCH)
- return -ENOENT;
- if (k == GLOB_NOSPACE)
- return -ENOMEM;
- if (k != 0)
- return errno > 0 ? -errno : -EIO;
- if (strv_isempty(g.gl_pathv))
- return -ENOENT;
+ k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
+ if (k == -ENOENT)
+ return false;
+ if (k < 0)
+ return k;
+ return true;
+}
+
+int glob_extend(char ***strv, const char *path) {
+ _cleanup_globfree_ glob_t g = {};
+ int k;
- STRV_FOREACH(p, g.gl_pathv) {
- k = strv_extend(strv, *p);
- if (k < 0)
- return k;
- }
+ k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
+ if (k < 0)
+ return k;
- return 0;
+ return strv_extend_strv(strv, g.gl_pathv, false);
}
diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h
index 5d8fb47a26..e1f6083afa 100644
--- a/src/basic/glob-util.h
+++ b/src/basic/glob-util.h
@@ -19,12 +19,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <glob.h>
#include <stdbool.h>
#include <string.h>
#include "macro.h"
#include "string-util.h"
+/* Note: this function modifies pglob to set various functions. */
+int safe_glob(const char *path, int flags, glob_t *pglob);
+
int glob_exists(const char *path);
int glob_extend(char ***strv, const char *path);
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index bdaca264ff..ff040e7a55 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -182,18 +182,11 @@ int rm_rf(const char *path, RemoveFlags flags) {
/* We refuse to clean the root file system with this
* call. This is extra paranoia to never cause a really
* seriously broken system. */
- if (path_equal(path, "/")) {
+ if (path_equal_or_files_same(path, "/")) {
log_error("Attempted to remove entire root file system, and we can't allow that.");
return -EPERM;
}
- /* Another safe-check. Removing "/path/.." could easily remove entire root as well.
- * It's especially easy to do using globs in tmpfiles, like "/path/.*", which the glob()
- * function expands to both "/path/." and "/path/..".
- * Return -EINVAL to be consistent with rmdir("/path/."). */
- if (endswith(path, "/..") || endswith(path, "/../"))
- return -EINVAL;
-
if ((flags & (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) == (REMOVE_SUBVOLUME|REMOVE_ROOT|REMOVE_PHYSICAL)) {
/* Try to remove as subvolume first */
r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c
index 4ac11a9bb0..b22d37b62d 100644
--- a/src/boot/efi/measure.c
+++ b/src/boot/efi/measure.c
@@ -199,7 +199,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
event_number = 1;
status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7,
- tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
+ (EFI_TCG *) tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
if (EFI_ERROR(status))
return status;
@@ -219,7 +219,7 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 p
*/
static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg)
{
- return uefi_call_wrapper(tcg->GetEventLog, 5, tcg,
+ return uefi_call_wrapper(tcg->GetEventLog, 5, (EFI_TCG2 *) tcg,
EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL,
NULL, NULL);
}
@@ -254,7 +254,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32
CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len);
- status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, tcg, 0, buffer, buffer_size, tcg_event);
+ status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, (EFI_TCG2 *) tcg, 0, buffer, buffer_size, tcg_event);
uefi_call_wrapper(BS->FreePool, 1, tcg_event);
diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h
index a2cfe817d0..43aa8a0058 100644
--- a/src/boot/efi/measure.h
+++ b/src/boot/efi/measure.h
@@ -13,9 +13,6 @@
#ifndef __SDBOOT_MEASURE_H
#define __SDBOOT_MEASURE_H
-#ifndef SD_TPM_PCR
-#define SD_TPM_PCR 8
-#endif
-
EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
+
#endif
diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c
index 67f3a99860..7ebb02fa8c 100644
--- a/src/cgtop/cgtop.c
+++ b/src/cgtop/cgtop.c
@@ -75,6 +75,7 @@ static usec_t arg_delay = 1*USEC_PER_SEC;
static char* arg_machine = NULL;
static char* arg_root = NULL;
static bool arg_recursive = true;
+static bool arg_recursive_unset = false;
static enum {
COUNT_PIDS,
@@ -732,7 +733,6 @@ static int parse_argv(int argc, char *argv[]) {
{}
};
- bool recursive_unset = false;
int c, r;
assert(argc >= 1);
@@ -852,7 +852,7 @@ static int parse_argv(int argc, char *argv[]) {
}
arg_recursive = r;
- recursive_unset = r == 0;
+ arg_recursive_unset = r == 0;
break;
case 'M':
@@ -873,11 +873,6 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
- if (recursive_unset && arg_count == COUNT_PIDS) {
- log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
- return -EINVAL;
- }
-
return 1;
}
@@ -902,6 +897,10 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ goto finish;
+
r = cg_mask_supported(&mask);
if (r < 0) {
log_error_errno(r, "Failed to determine supported controllers: %m");
@@ -910,9 +909,10 @@ int main(int argc, char *argv[]) {
arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES;
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
+ if (arg_recursive_unset && arg_count == COUNT_PIDS) {
+ log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
+ return -EINVAL;
+ }
r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root);
if (r < 0) {
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index f15bb2196c..b0645ce294 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -748,6 +748,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
diff --git a/src/core/device.c b/src/core/device.c
index 0e67c96552..da008f6041 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -112,7 +112,7 @@ static void device_init(Unit *u) {
* indefinitely for plugged in devices, something which cannot
* happen for the other units since their operations time out
* anyway. */
- u->job_timeout = u->manager->default_timeout_start_usec;
+ u->job_running_timeout = u->manager->default_timeout_start_usec;
u->ignore_on_isolate = true;
}
diff --git a/src/core/execute.c b/src/core/execute.c
index 2056e2273c..9c1aa4cf98 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -3231,11 +3231,10 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
STRV_FOREACH(i, c->environment_files) {
char *fn;
- int k;
+ int k, n;
bool ignore = false;
char **p;
_cleanup_globfree_ glob_t pglob = {};
- int count, n;
fn = *i;
@@ -3253,23 +3252,19 @@ int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
}
/* Filename supports globbing, take all matching files */
- errno = 0;
- if (glob(fn, 0, NULL, &pglob) != 0) {
+ k = safe_glob(fn, 0, &pglob);
+ if (k < 0) {
if (ignore)
continue;
strv_free(r);
- return errno > 0 ? -errno : -EINVAL;
+ return k;
}
- count = pglob.gl_pathc;
- if (count == 0) {
- if (ignore)
- continue;
- strv_free(r);
- return -EINVAL;
- }
- for (n = 0; n < count; n++) {
+ /* When we don't match anything, -ENOENT should be returned */
+ assert(pglob.gl_pathc > 0);
+
+ for (n = 0; n < pglob.gl_pathc; n++) {
k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
if (k < 0) {
if (ignore)
diff --git a/src/core/job.c b/src/core/job.c
index a02f1bb2bc..5067006d63 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -576,6 +576,7 @@ int job_run_and_invalidate(Job *j) {
if (!job_is_runnable(j))
return -EAGAIN;
+ job_start_timer(j, true);
job_set_state(j, JOB_RUNNING);
job_add_to_dbus_queue(j);
@@ -949,22 +950,45 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user
return 0;
}
-int job_start_timer(Job *j) {
+int job_start_timer(Job *j, bool job_running) {
int r;
+ usec_t run_begin, timeout_time, old_timeout_time;
- if (j->timer_event_source)
- return 0;
+ if (job_running) {
+ if (j->unit->job_running_timeout == USEC_INFINITY)
+ return 0;
- j->begin_usec = now(CLOCK_MONOTONIC);
+ run_begin = now(CLOCK_MONOTONIC);
+ timeout_time = usec_add(run_begin, j->unit->job_running_timeout);
- if (j->unit->job_timeout == USEC_INFINITY)
- return 0;
+ if (j->timer_event_source) {
+ /* Update only if JobRunningTimeoutSec= results in earlier timeout */
+ r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time);
+ if (r < 0)
+ return r;
+
+ if (old_timeout_time <= timeout_time)
+ return 0;
+
+ return sd_event_source_set_time(j->timer_event_source, timeout_time);
+ }
+ } else {
+ if (j->timer_event_source)
+ return 0;
+
+ j->begin_usec = now(CLOCK_MONOTONIC);
+
+ if (j->unit->job_timeout == USEC_INFINITY)
+ return 0;
+
+ timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
+ }
r = sd_event_add_time(
j->manager->event,
&j->timer_event_source,
CLOCK_MONOTONIC,
- usec_add(j->begin_usec, j->unit->job_timeout), 0,
+ timeout_time, 0,
job_dispatch_timer, j);
if (r < 0)
return r;
diff --git a/src/core/job.h b/src/core/job.h
index bea743f462..8b3d38fc60 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -220,7 +220,7 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u);
void job_add_to_run_queue(Job *j);
void job_add_to_dbus_queue(Job *j);
-int job_start_timer(Job *j);
+int job_start_timer(Job *j, bool job_running);
int job_run_and_invalidate(Job *j);
int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index cb9e6fea27..97adbdd7bb 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -194,6 +194,7 @@ Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0,
Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate)
Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0
Unit.JobTimeoutSec, config_parse_sec_fix_0, 0, offsetof(Unit, job_timeout)
+Unit.JobRunningTimeoutSec, config_parse_sec, 0, offsetof(Unit, job_running_timeout)
Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action)
Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg)
Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
diff --git a/src/core/service.c b/src/core/service.c
index a63c6d8bc3..b45929e535 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2163,7 +2163,6 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
unsigned idx;
const char *type;
char **arg;
- _cleanup_strv_free_ char **escaped_args = NULL;
_cleanup_free_ char *args = NULL, *p = NULL;
size_t allocated = 0, length = 0;
@@ -2306,7 +2305,7 @@ static int service_deserialize_exec_command(Unit *u, const char *key, const char
bool control, found = false;
ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID;
ExecCommand *command = NULL;
- _cleanup_free_ char *args = NULL, *path = NULL;
+ _cleanup_free_ char *path = NULL;
_cleanup_strv_free_ char **argv = NULL;
enum ExecCommandState {
diff --git a/src/core/transaction.c b/src/core/transaction.c
index b6d1062414..a2dfd8ae90 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -632,7 +632,7 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) {
job_add_to_run_queue(j);
job_add_to_dbus_queue(j);
- job_start_timer(j);
+ job_start_timer(j, false);
job_shutdown_magic(j);
}
diff --git a/src/core/unit.c b/src/core/unit.c
index 25ea5a8591..01fa0d0d46 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -99,6 +99,7 @@ Unit *unit_new(Manager *m, size_t size) {
u->on_failure_job_mode = JOB_REPLACE;
u->cgroup_inotify_wd = -1;
u->job_timeout = USEC_INFINITY;
+ u->job_running_timeout = USEC_INFINITY;
u->ref_uid = UID_INVALID;
u->ref_gid = GID_INVALID;
u->cpu_usage_last = NSEC_INFINITY;
@@ -1336,6 +1337,9 @@ int unit_load(Unit *u) {
goto fail;
}
+ if (u->job_running_timeout != USEC_INFINITY && u->job_running_timeout > u->job_timeout)
+ log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect.");
+
unit_update_cgroup_members_masks(u);
}
diff --git a/src/core/unit.h b/src/core/unit.h
index 8052c234fd..cf21b37e22 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -114,6 +114,7 @@ struct Unit {
/* Job timeout and action to take */
usec_t job_timeout;
+ usec_t job_running_timeout;
EmergencyAction job_timeout_action;
char *job_timeout_reboot_arg;
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 50d350fce8..b6c1a8781b 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -399,6 +399,10 @@ static int add_mount(
if (r < 0)
return r;
+ r = generator_write_device_deps(dest, what, where, opts);
+ if (r < 0)
+ return r;
+
r = write_mount_timeout(f, where, opts);
if (r < 0)
return r;
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 4c745288f5..78840dd882 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -394,7 +394,6 @@ int pull_verify(PullJob *main_job,
PullJob *signature_job) {
_cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 };
- _cleanup_free_ char *fn = NULL;
_cleanup_close_ int sig_file = -1;
char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX";
_cleanup_(sigkill_waitp) pid_t pid = 0;
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index fd2e472f09..a15eac1f1f 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -580,7 +580,6 @@ static int raw_pull_job_on_open_disk_generic(
const char *extra,
char **temp_path) {
- _cleanup_free_ char *p = NULL;
int r;
assert(i);
diff --git a/src/journal-remote/log-generator.py b/src/journal-remote/log-generator.py
index 7b434b334e..c2f945bb47 100755
--- a/src/journal-remote/log-generator.py
+++ b/src/journal-remote/log-generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
import sys
import argparse
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 14cb01a600..243d5198d9 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -613,6 +613,9 @@ static int journal_file_verify_header(JournalFile *f) {
return -EBUSY;
}
+ if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0)
+ return -EBADMSG;
+
/* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
* be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
* bisection. */
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 092a1eabb0..337241a815 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -349,6 +349,45 @@ int config_parse_iaid(const char *unit,
return 0;
}
+int config_parse_bridge_port_priority(
+ 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) {
+
+ uint16_t i;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou16(rvalue, &i);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse bridge port priority, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue);
+ return 0;
+ }
+
+ *((uint16_t *)data) = i;
+
+ return 0;
+}
+
+
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
unsigned i;
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 5bcd577167..4666f174e9 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -26,6 +26,9 @@
#include "condition.h"
#include "udev.h"
+#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
+#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
+
bool net_match_config(const struct ether_addr *match_mac,
char * const *match_path,
char * const *match_driver,
@@ -62,6 +65,10 @@ int config_parse_iaid(const char *unit, const char *filename, unsigned line,
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_bridge_port_priority(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);
+
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 1d3be9b862..83e57d43f7 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -131,6 +131,7 @@ static int ndisc_reset(sd_ndisc *nd) {
nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
nd->recv_event_source = sd_event_source_unref(nd->recv_event_source);
nd->fd = safe_close(nd->fd);
+ nd->nd_sent = 0;
return 0;
}
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 248bc90788..923f7dd10c 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -26,6 +26,7 @@
#include <linux/veth.h>
#include <linux/if_bridge.h>
#include <linux/if_addr.h>
+#include <linux/if_addrlabel.h>
#include <linux/if.h>
#include <linux/ip.h>
#include <linux/if_link.h>
@@ -586,22 +587,35 @@ static const NLTypeSystem rtnl_neigh_type_system = {
.types = rtnl_neigh_types,
};
+static const NLType rtnl_addrlabel_types[] = {
+ [IFAL_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
+ [IFAL_LABEL] = { .type = NETLINK_TYPE_U32 },
+};
+
+static const NLTypeSystem rtnl_addrlabel_type_system = {
+ .count = ELEMENTSOF(rtnl_addrlabel_types),
+ .types = rtnl_addrlabel_types,
+};
+
static const NLType rtnl_types[] = {
- [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
- [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
- [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
- [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
- [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
- [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
- [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
- [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
- [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
- [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
- [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
- [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
- [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
- [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
- [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+ [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
+ [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
+ [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+ [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+ [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+ [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
+ [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+ [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+ [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
+ [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+ [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+ [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
+ [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+ [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+ [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
+ [RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
+ [RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
+ [RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
};
const NLTypeSystem type_system_root = {
diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h
index f49bf4eaa6..49bb226ef3 100644
--- a/src/libsystemd/sd-netlink/netlink-util.h
+++ b/src/libsystemd/sd-netlink/netlink-util.h
@@ -32,6 +32,10 @@ bool rtnl_message_type_is_addr(uint16_t type);
bool rtnl_message_type_is_route(uint16_t type);
bool rtnl_message_type_is_neigh(uint16_t type);
+static inline bool rtnl_message_type_is_addrlabel(uint16_t type) {
+ return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL);
+}
+
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu);
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index b543b5f20c..d5f8b7d15e 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -18,6 +18,7 @@
***/
#include <netinet/in.h>
+#include <linux/if_addrlabel.h>
#include <stdbool.h>
#include <unistd.h>
@@ -700,3 +701,42 @@ int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) {
return -EOPNOTSUPP;
}
+
+int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) {
+ struct ifaddrlblmsg *addrlabel;
+ int r;
+
+ assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ r = message_new(rtnl, ret, nlmsg_type);
+ if (r < 0)
+ return r;
+
+ if (nlmsg_type == RTM_NEWADDRLABEL)
+ (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
+
+ addrlabel = NLMSG_DATA((*ret)->hdr);
+
+ addrlabel->ifal_family = ifal_family;
+ addrlabel->ifal_index = ifindex;
+
+ return 0;
+}
+
+int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
+ struct ifaddrlblmsg *addrlabel;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->hdr, -EINVAL);
+ assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
+
+ addrlabel = NLMSG_DATA(m->hdr);
+
+ if (prefixlen > 128)
+ return -ERANGE;
+
+ addrlabel->ifal_prefixlen = prefixlen;
+
+ return 0;
+}
diff --git a/src/network/meson.build b/src/network/meson.build
index ebd4e62eb3..5f97cc197b 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -27,6 +27,8 @@ sources = files('''
netdev/vxlan.h
netdev/geneve.c
netdev/geneve.h
+ networkd-address-label.c
+ networkd-address-label.h
networkd-address-pool.c
networkd-address-pool.h
networkd-address.c
diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c
index 07c69f4711..e71ea58a10 100644
--- a/src/network/netdev/geneve.c
+++ b/src/network/netdev/geneve.c
@@ -238,36 +238,6 @@ int config_parse_geneve_address(const char *unit,
return 0;
}
-int config_parse_geneve_destination_port(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) {
- Geneve *v = userdata;
- uint16_t port;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = parse_ip_port(rvalue, &port);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve destination port '%s'.", rvalue);
- return 0;
- }
-
- v->dest_port = port;
-
- return 0;
-}
-
int config_parse_geneve_flow_label(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/network/netdev/geneve.h b/src/network/netdev/geneve.h
index d97dac892c..bde28bac55 100644
--- a/src/network/netdev/geneve.h
+++ b/src/network/netdev/geneve.h
@@ -25,7 +25,6 @@ typedef struct Geneve Geneve;
#include "netdev.h"
#include "networkd-link.h"
#include "networkd-network.h"
-#include "netdev.h"
#define GENEVE_VID_MAX (1u << 24) - 1
@@ -74,17 +73,6 @@ int config_parse_geneve_address(const char *unit,
void *data,
void *userdata);
-int config_parse_geneve_destination_port(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);
-
int config_parse_geneve_flow_label(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 6016b99b54..ed943789d7 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -79,7 +79,7 @@ VXLAN.FDBAgeingSec, config_parse_sec, 0,
VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy)
VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb)
VXLAN.PortRange, config_parse_port_range, 0, 0
-VXLAN.DestinationPort, config_parse_destination_port, 0, offsetof(VxLan, dest_port)
+VXLAN.DestinationPort, config_parse_ip_port, 0, offsetof(VxLan, dest_port)
VXLAN.FlowLabel, config_parse_flow_label, 0, 0
GENEVE.Id, config_parse_geneve_vni, 0, offsetof(Geneve, id)
GENEVE.Remote, config_parse_geneve_address, 0, offsetof(Geneve, remote)
@@ -88,7 +88,7 @@ GENEVE.TTL, config_parse_uint8, 0,
GENEVE.UDPChecksum, config_parse_bool, 0, offsetof(Geneve, udpcsum)
GENEVE.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx)
GENEVE.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx)
-GENEVE.DestinationPort, config_parse_geneve_destination_port, 0, offsetof(Geneve, dest_port)
+GENEVE.DestinationPort, config_parse_ip_port, 0, offsetof(Geneve, dest_port)
GENEVE.FlowLabel, config_parse_geneve_flow_label, 0, 0
Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue)
Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 3848c863c5..43884581ca 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -28,6 +28,7 @@
#include "network-internal.h"
#include "netdev/netdev.h"
#include "networkd-manager.h"
+#include "networkd-link.h"
#include "siphash24.h"
#include "stat-util.h"
#include "string-table.h"
@@ -221,6 +222,13 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h
assert(link);
assert(callback);
+ if (link->flags & IFF_UP) {
+ log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname);
+ r = link_down(link);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not bring link down: %m");
+ }
+
r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m");
diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c
index 7f20e6cdfe..b5b7aec2c0 100644
--- a/src/network/netdev/vxlan.c
+++ b/src/network/netdev/vxlan.c
@@ -271,36 +271,6 @@ int config_parse_port_range(const char *unit,
return 0;
}
-int config_parse_destination_port(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) {
- VxLan *v = userdata;
- uint16_t port;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = parse_ip_port(rvalue, &port);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue);
- return 0;
- }
-
- v->dest_port = port;
-
- return 0;
-}
-
int config_parse_flow_label(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/network/netdev/vxlan.h b/src/network/netdev/vxlan.h
index 7f97a9edc4..1eeda022a2 100644
--- a/src/network/netdev/vxlan.h
+++ b/src/network/netdev/vxlan.h
@@ -86,17 +86,6 @@ int config_parse_port_range(const char *unit,
void *data,
void *userdata);
-int config_parse_destination_port(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);
-
int config_parse_flow_label(const char *unit,
const char *filename,
unsigned line,
diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c
new file mode 100644
index 0000000000..1248719cf3
--- /dev/null
+++ b/src/network/networkd-address-label.c
@@ -0,0 +1,257 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2017 Susant Sahani
+
+ 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 distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <net/if.h>
+#include <linux/if_addrlabel.h>
+
+#include "alloc-util.h"
+#include "conf-parser.h"
+#include "networkd-address-label.h"
+#include "netlink-util.h"
+#include "networkd-manager.h"
+#include "parse-util.h"
+#include "socket-util.h"
+
+int address_label_new(AddressLabel **ret) {
+ _cleanup_address_label_free_ AddressLabel *addrlabel = NULL;
+
+ addrlabel = new0(AddressLabel, 1);
+ if (!addrlabel)
+ return -ENOMEM;
+
+ *ret = addrlabel;
+ addrlabel = NULL;
+
+ return 0;
+}
+
+void address_label_free(AddressLabel *label) {
+ if (!label)
+ return;
+
+ if (label->network) {
+ LIST_REMOVE(labels, label->network->address_labels, label);
+ assert(label->network->n_address_labels > 0);
+ label->network->n_address_labels--;
+
+ if (label->section) {
+ hashmap_remove(label->network->address_labels_by_section, label->section);
+ network_config_section_free(label->section);
+ }
+ }
+
+ free(label);
+}
+
+static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
+ _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
+ _cleanup_address_label_free_ AddressLabel *label = NULL;
+ int r;
+
+ assert(network);
+ assert(ret);
+ assert(!!filename == (section_line > 0));
+
+ r = network_config_section_new(filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ label = hashmap_get(network->address_labels_by_section, n);
+ if (label) {
+ *ret = label;
+ label = NULL;
+
+ return 0;
+ }
+
+ r = address_label_new(&label);
+ if (r < 0)
+ return r;
+
+ label->section = n;
+ n = NULL;
+
+ r = hashmap_put(network->address_labels_by_section, label->section, label);
+ if (r < 0)
+ return r;
+
+ label->network = network;
+ LIST_APPEND(labels, network->address_labels, label);
+ network->n_address_labels++;
+
+ *ret = label;
+ label = NULL;
+
+ return 0;
+}
+
+int address_label_configure(
+ AddressLabel *label,
+ Link *link,
+ sd_netlink_message_handler_t callback,
+ bool update) {
+
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(label);
+ assert(link);
+ assert(link->ifindex > 0);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+
+ r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL,
+ link->ifindex, label->family);
+ if (r < 0)
+ return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
+
+ r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen);
+ if (r < 0)
+ return log_error_errno(r, "Could not set prefixlen: %m");
+
+ r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label);
+ if (r < 0)
+ return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m");
+
+ r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6);
+ if (r < 0)
+ return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
+}
+
+int config_parse_address_label_prefix(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_address_label_free_ AddressLabel *n = NULL;
+ Network *network = userdata;
+ const char *prefix, *e;
+ union in_addr_union buffer;
+ int r, f;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = address_label_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ /* AddressLabel=prefix/prefixlen */
+
+ /* prefixlen */
+ e = strchr(rvalue, '/');
+ if (e) {
+ unsigned i;
+
+ r = safe_atou(e + 1, &i);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1);
+ return 0;
+ }
+
+ if (i > 128) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is out of range, ignoring assignment: %s", e + 1);
+ return 0;
+ }
+
+ n->prefixlen = (unsigned char) i;
+
+ prefix = strndupa(rvalue, e - rvalue);
+ } else
+ prefix = rvalue;
+
+ r = in_addr_from_string_auto(prefix, &f, &buffer);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", prefix);
+ return 0;
+ }
+
+ if (f != AF_INET6) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Address label family is not IPv6, ignoring assignment: %s", prefix);
+ return 0;
+ }
+
+ n->family = f;
+ n->in_addr = buffer;
+
+ n = NULL;
+
+ return 0;
+}
+
+int config_parse_address_label(
+ 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_address_label_free_ AddressLabel *n = NULL;
+ Network *network = userdata;
+ uint32_t k;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = address_label_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (k == 0xffffffffUL) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Adress label is invalid, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n->label = k;
+ n = NULL;
+
+ return 0;
+}
diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h
new file mode 100644
index 0000000000..05bb24924c
--- /dev/null
+++ b/src/network/networkd-address-label.h
@@ -0,0 +1,59 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2017 Susant Sahani
+
+ 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 distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "in-addr-util.h"
+
+typedef struct AddressLabel AddressLabel;
+
+#include "networkd-link.h"
+#include "networkd-network.h"
+
+typedef struct Network Network;
+typedef struct Link Link;
+typedef struct NetworkConfigSection NetworkConfigSection;
+
+struct AddressLabel {
+ Network *network;
+ Link *link;
+ NetworkConfigSection *section;
+
+ int family;
+ unsigned char prefixlen;
+ uint32_t label;
+
+ union in_addr_union in_addr;
+
+ LIST_FIELDS(AddressLabel, labels);
+};
+
+int address_label_new(AddressLabel **ret);
+void address_label_free(AddressLabel *label);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(AddressLabel*, address_label_free);
+#define _cleanup_address_label_free_ _cleanup_(address_label_freep)
+
+int address_label_configure(AddressLabel *address, Link *link, sd_netlink_message_handler_t callback, bool update);
+
+int config_parse_address_label(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);
+int config_parse_address_label_prefix(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);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 1797f144b6..6ed8380942 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -853,6 +853,35 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
return 1;
}
+static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ _cleanup_link_unref_ Link *link = userdata;
+ int r;
+
+ assert(rtnl);
+ assert(m);
+ assert(link);
+ assert(link->ifname);
+ assert(link->link_messages > 0);
+
+ link->link_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 address label: %m");
+ else if (r >= 0)
+ manager_rtnl_process_address(rtnl, m, link->manager);
+
+ if (link->link_messages == 0) {
+ log_link_debug(link, "Addresses label set");
+ link_enter_set_routes(link);
+ }
+
+ return 1;
+}
+
static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
_cleanup_free_ struct in_addr *addresses = NULL;
size_t n_addresses = 0, n_allocated = 0;
@@ -965,6 +994,7 @@ static int link_set_bridge_fdb(Link *link) {
}
static int link_enter_set_addresses(Link *link) {
+ AddressLabel *label;
Address *ad;
int r;
@@ -989,6 +1019,17 @@ static int link_enter_set_addresses(Link *link) {
link->link_messages++;
}
+ LIST_FOREACH(labels, label, link->network->address_labels) {
+ r = address_label_configure(label, link, address_label_handler, false);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set address label: %m");
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->link_messages++;
+ }
+
/* now that we can figure out a default address for the dhcp server,
start it */
if (link_dhcp4_server_enabled(link)) {
@@ -1603,7 +1644,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
return 1;
}
-static int link_up(Link *link) {
+int link_up(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
uint8_t ipv6ll_mode;
int r;
@@ -1724,7 +1765,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
return 1;
}
-static int link_down(Link *link) {
+int link_down(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 010b38248a..be5c4f3284 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -33,8 +33,6 @@
#include "list.h"
#include "set.h"
-#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
-
typedef enum LinkState {
LINK_STATE_PENDING,
LINK_STATE_ENSLAVING,
@@ -140,6 +138,9 @@ int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
+int link_up(Link *link);
+int link_down(Link *link);
+
int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 3743113825..ee8bd6faf7 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -79,6 +79,8 @@ Address.DuplicateAddressDetection, config_parse_address_flags,
Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0
Address.PrefixRoute, config_parse_address_flags, 0, 0
Address.AutoJoin, config_parse_address_flags, 0, 0
+IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0
+IPv6AddressLabel.Label, config_parse_address_label, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
@@ -127,7 +129,7 @@ Bridge.HairPin, config_parse_bool,
Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave)
Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root)
Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
-Bridge.Priority, config_parse_uint16, 0, offsetof(Network, priority)
+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
BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index dd29b4ca48..0c0e661909 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -114,6 +114,7 @@ static int network_load_one(Manager *manager, const char *filename) {
LIST_HEAD_INIT(network->static_routes);
LIST_HEAD_INIT(network->static_fdb_entries);
LIST_HEAD_INIT(network->ipv6_proxy_ndp_addresses);
+ LIST_HEAD_INIT(network->address_labels);
network->stacked_netdevs = hashmap_new(&string_hash_ops);
if (!network->stacked_netdevs)
@@ -131,6 +132,10 @@ static int network_load_one(Manager *manager, const char *filename) {
if (!network->fdb_entries_by_section)
return log_oom();
+ network->address_labels_by_section = hashmap_new(&network_config_hash_ops);
+ if (!network->address_labels_by_section)
+ return log_oom();
+
network->filename = strdup(filename);
if (!network->filename)
return log_oom();
@@ -192,6 +197,7 @@ static int network_load_one(Manager *manager, const char *filename) {
"Link\0"
"Network\0"
"Address\0"
+ "IPv6AddressLabel\0"
"Route\0"
"DHCP\0"
"DHCPv4\0" /* compat */
@@ -271,6 +277,7 @@ void network_free(Network *network) {
Address *address;
FdbEntry *fdb_entry;
IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
+ AddressLabel *label;
Iterator i;
if (!network)
@@ -318,9 +325,13 @@ 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 ((label = network->address_labels))
+ address_label_free(label);
+
hashmap_free(network->addresses_by_section);
hashmap_free(network->routes_by_section);
hashmap_free(network->fdb_entries_by_section);
+ hashmap_free(network->address_labels_by_section);
if (network->manager) {
if (network->manager->networks)
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index d6f418d521..28ef285be6 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -28,6 +28,7 @@
#include "resolve-util.h"
#include "networkd-address.h"
+#include "networkd-address-label.h"
#include "networkd-brvlan.h"
#include "networkd-fdb.h"
#include "networkd-lldp-tx.h"
@@ -202,15 +203,18 @@ struct Network {
LIST_HEAD(Route, static_routes);
LIST_HEAD(FdbEntry, static_fdb_entries);
LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
+ LIST_HEAD(AddressLabel, address_labels);
unsigned n_static_addresses;
unsigned n_static_routes;
unsigned n_static_fdb_entries;
unsigned n_ipv6_proxy_ndp_addresses;
+ unsigned n_address_labels;
Hashmap *addresses_by_section;
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
+ Hashmap *address_labels_by_section;
struct in_addr_data *dns;
unsigned n_dns;
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index fd00d0957a..905dbc4c74 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1158,6 +1158,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? 1ULL << CAP_NET_ADMIN : 0)) & ~minus;
+ r = cg_unified_flush();
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
+
e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE");
if (e)
arg_container_service_name = e;
@@ -3545,10 +3549,6 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
- r = cg_unified_flush();
- if (r < 0)
- return log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m");
-
/* Make sure rename_process() in the stub init process can work */
saved_argv = argv;
saved_argc = argc;
diff --git a/src/resolve/generate-dns_type-gperf.py b/src/resolve/generate-dns_type-gperf.py
index fb36c850af..8a0b43c277 100644
--- a/src/resolve/generate-dns_type-gperf.py
+++ b/src/resolve/generate-dns_type-gperf.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
"""Generate %-from-name.gperf from %-list.txt
"""
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index d8393cbc8d..dae521ef9f 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -960,3 +960,40 @@ int config_parse_ifname(
return 0;
}
+
+int config_parse_ip_port(
+ 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) {
+
+ uint16_t *s = data;
+ uint16_t port;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *s = 0;
+ return 0;
+ }
+
+ r = parse_ip_port(rvalue, &port);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue);
+ return 0;
+ }
+
+ *s = port;
+
+ return 0;
+}
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 82ea5c1288..ce1113485d 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -140,6 +140,7 @@ int config_parse_log_level(const char *unit, const char *filename, unsigned line
int config_parse_signal(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);
int config_parse_personality(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);
int config_parse_ifname(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);
+int config_parse_ip_port(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);
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
int function(const char *unit, \
diff --git a/src/shared/efivars.c b/src/shared/efivars.c
index 8631a5a5d9..8229e6b183 100644
--- a/src/shared/efivars.c
+++ b/src/shared/efivars.c
@@ -269,6 +269,7 @@ int efi_set_variable(
_cleanup_close_ int fd = -1;
assert(name);
+ assert(value);
if (asprintf(&p,
"/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
diff --git a/src/shared/generator.c b/src/shared/generator.c
index 9a069b2f97..19ec133772 100644
--- a/src/shared/generator.c
+++ b/src/shared/generator.c
@@ -188,10 +188,49 @@ int generator_write_timeouts(
return write_drop_in_format(dir, unit, 50, "device-timeout",
"# Automatically generated by %s\n\n"
- "[Unit]\nJobTimeoutSec=%s",
+ "[Unit]\nJobRunningTimeoutSec=%s",
program_invocation_short_name, timeout);
}
+int generator_write_device_deps(
+ const char *dir,
+ const char *what,
+ const char *where,
+ const char *opts) {
+
+ /* fstab records that specify _netdev option should apply the network
+ * ordering on the actual device depending on network connection. If we
+ * are not mounting real device (NFS, CIFS), we rely on _netdev effect
+ * on the mount unit itself. */
+
+ _cleanup_free_ char *node = NULL, *unit = NULL;
+ int r;
+
+ if (!fstab_test_option(opts, "_netdev\0"))
+ return 0;
+
+ node = fstab_node_to_udev_node(what);
+ if (!node)
+ return log_oom();
+
+ /* Nothing to apply dependencies to. */
+ if (!is_device_path(node))
+ return 0;
+
+ r = unit_name_from_path(node, ".device", &unit);
+ if (r < 0)
+ return log_error_errno(r, "Failed to make unit name from path: %m");
+
+ /* See mount_add_default_dependencies for explanation why we create such
+ * dependencies. */
+ return write_drop_in_format(dir, unit, 50, "netdev-dependencies",
+ "# Automatically generated by %s\n\n"
+ "[Unit]\n"
+ "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n"
+ "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n",
+ program_invocation_short_name);
+}
+
int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
_cleanup_free_ char *unit = NULL;
int r;
diff --git a/src/shared/generator.h b/src/shared/generator.h
index a6017c1b76..825d934c8e 100644
--- a/src/shared/generator.h
+++ b/src/shared/generator.h
@@ -35,6 +35,12 @@ int generator_write_timeouts(
const char *opts,
char **filtered);
+int generator_write_device_deps(
+ const char *dir,
+ const char *what,
+ const char *where,
+ const char *opts);
+
int generator_write_initrd_root_device_deps(
const char *dir,
const char *what);
diff --git a/src/shared/meson.build b/src/shared/meson.build
index 49a7d9f30b..b684e5b543 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -127,10 +127,10 @@ libshared = shared_library(
basic_sources,
journal_internal_sources,
libsystemd_internal_sources,
+ libudev_sources,
include_directories : includes,
link_args : ['-shared'],
c_args : ['-fvisibility=default'],
- link_with : [libudev],
dependencies : [threads,
librt,
libcap,
diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h
index 7efa8ebe5a..aa39e0a0db 100644
--- a/src/systemd/sd-netlink.h
+++ b/src/systemd/sd-netlink.h
@@ -155,6 +155,9 @@ int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *family);
int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state);
int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags);
+int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family);
+int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
+
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref);
diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py
index a3350c8a81..357cce8e44 100644
--- a/src/test/generate-sym-test.py
+++ b/src/test/generate-sym-test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
import sys, re
print('#include <stdio.h>')
diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c
index 9eea3eb608..af866e004b 100644
--- a/src/test/test-glob-util.c
+++ b/src/test/test-glob-util.c
@@ -18,12 +18,17 @@
***/
#include <fcntl.h>
+#include <glob.h>
+#include <sys/stat.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "dirent-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "glob-util.h"
#include "macro.h"
+#include "rm-rf.h"
static void test_glob_exists(void) {
char name[] = "/tmp/test-glob_exists.XXXXXX";
@@ -43,8 +48,69 @@ static void test_glob_exists(void) {
assert_se(r == 0);
}
+static void test_glob_no_dot(void) {
+ char template[] = "/tmp/test-glob-util.XXXXXXX";
+ const char *fn;
+
+ _cleanup_globfree_ glob_t g = {
+ .gl_closedir = (void (*)(void *)) closedir,
+ .gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot,
+ .gl_opendir = (void *(*)(const char *)) opendir,
+ .gl_lstat = lstat,
+ .gl_stat = stat,
+ };
+
+ int r;
+
+ assert_se(mkdtemp(template));
+
+ fn = strjoina(template, "/*");
+ r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
+ assert_se(r == GLOB_NOMATCH);
+
+ fn = strjoina(template, "/.*");
+ r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
+ assert_se(r == GLOB_NOMATCH);
+
+ (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
+static void test_safe_glob(void) {
+ char template[] = "/tmp/test-glob-util.XXXXXXX";
+ const char *fn, *fn2, *fname;
+
+ _cleanup_globfree_ glob_t g = {};
+ int r;
+
+ assert_se(mkdtemp(template));
+
+ fn = strjoina(template, "/*");
+ r = safe_glob(fn, 0, &g);
+ assert_se(r == -ENOENT);
+
+ fn2 = strjoina(template, "/.*");
+ r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g);
+ assert_se(r == -ENOENT);
+
+ fname = strjoina(template, "/.foobar");
+ assert_se(touch(fname) == 0);
+
+ r = safe_glob(fn, 0, &g);
+ assert_se(r == -ENOENT);
+
+ r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g);
+ assert_se(r == 0);
+ assert_se(g.gl_pathc == 1);
+ assert_se(streq(g.gl_pathv[0], fname));
+ assert_se(g.gl_pathv[1] == NULL);
+
+ (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL);
+}
+
int main(void) {
test_glob_exists();
+ test_glob_no_dot();
+ test_safe_glob();
return 0;
}
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 22df20a1eb..ab62d0dad2 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -27,6 +27,7 @@
#include "mount-util.h"
#include "path-util.h"
#include "rm-rf.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
@@ -104,6 +105,38 @@ static void test_path(void) {
assert_se(!path_equal_ptr(NULL, "/a"));
}
+static void test_path_equal_root(void) {
+ /* Nail down the details of how path_equal("/", ...) works. */
+
+ assert_se(path_equal("/", "/"));
+ assert_se(path_equal("/", "//"));
+
+ assert_se(!path_equal("/", "/./"));
+ assert_se(!path_equal("/", "/../"));
+
+ assert_se(!path_equal("/", "/.../"));
+
+ /* Make sure that files_same works as expected. */
+
+ assert_se(files_same("/", "/") > 0);
+ assert_se(files_same("/", "//") > 0);
+
+ assert_se(files_same("/", "/./") > 0);
+ assert_se(files_same("/", "/../") > 0);
+
+ assert_se(files_same("/", "/.../") == -ENOENT);
+
+ /* The same for path_equal_or_files_same. */
+
+ assert_se(path_equal_or_files_same("/", "/"));
+ assert_se(path_equal_or_files_same("/", "//"));
+
+ assert_se(path_equal_or_files_same("/", "/./"));
+ assert_se(path_equal_or_files_same("/", "/../"));
+
+ assert_se(!path_equal_or_files_same("/", "/.../"));
+}
+
static void test_find_binary(const char *self) {
char *p;
@@ -551,6 +584,7 @@ int main(int argc, char **argv) {
log_open();
test_path();
+ test_path_equal_root();
test_find_binary(argv[0]);
test_prefixes();
test_path_join();
diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c
index 36389b7710..269adfd18f 100644
--- a/src/test/test-sizeof.c
+++ b/src/test/test-sizeof.c
@@ -32,6 +32,14 @@
strstr(STRINGIFY(t), "signed") ? "" : \
((t)-1 < (t)0 ? ", signed" : ", unsigned"));
+enum Enum {
+ enum_value,
+};
+
+enum BigEnum {
+ big_enum_value = UINT64_C(-1),
+};
+
int main(void) {
info(char);
info(signed char);
@@ -53,5 +61,8 @@ int main(void) {
info(usec_t);
info(__time_t);
+ info(enum Enum);
+ info(enum BigEnum);
+
return 0;
}
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index ed6a9adaa6..36488c9a5c 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -1093,19 +1093,14 @@ static int item_do_children(Item *i, const char *path, action_t action) {
static int glob_item(Item *i, action_t action, bool recursive) {
_cleanup_globfree_ glob_t g = {
- .gl_closedir = (void (*)(void *)) closedir,
- .gl_readdir = (struct dirent *(*)(void *)) readdir,
.gl_opendir = (void *(*)(const char *)) opendir_nomod,
- .gl_lstat = lstat,
- .gl_stat = stat,
};
int r = 0, k;
char **fn;
- errno = 0;
- k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
- if (k != 0 && k != GLOB_NOMATCH)
- return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
+ k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g);
+ if (k < 0 && k != -ENOENT)
+ return log_error_errno(k, "glob(%s) failed: %m", i->path);
STRV_FOREACH(fn, g.gl_pathv) {
k = action(i, *fn);
diff --git a/test/README.testsuite b/test/README.testsuite
index fa7e73ce3a..58f67f50fd 100644
--- a/test/README.testsuite
+++ b/test/README.testsuite
@@ -3,7 +3,7 @@ subdirectories named "test/TEST-??-*", which are run one by one.
To run the extended testsuite do the following:
-$ make all
+$ make all # Avoid the "sudo make" below building anything as root
$ cd test
$ sudo make clean check
...
diff --git a/test/create-sys-script.py b/test/create-sys-script.py
index 4b7abd24ae..402b4f83ab 100755
--- a/test/create-sys-script.py
+++ b/test/create-sys-script.py
@@ -1,6 +1,6 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
-OUTFILE_HEADER = """#!/usr/bin/python3
+OUTFILE_HEADER = """#!/usr/bin/env python3
#
# create-sys-script.py
#
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py
index dab01f1d8a..14739df493 100755
--- a/test/rule-syntax-check.py
+++ b/test/rule-syntax-check.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# Simple udev rules syntax checker
#
# (C) 2010 Canonical Ltd.
diff --git a/test/sys-script.py b/test/sys-script.py
index a9c0046667..6c9ee5ff83 100755
--- a/test/sys-script.py
+++ b/test/sys-script.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
#
# sys-script.py
#
diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py
index 16ea65690a..d116fffe38 100755
--- a/test/sysv-generator-test.py
+++ b/test/sysv-generator-test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
#
# systemd-sysv-generator integration test
#
diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py
index b974b1c133..39a9e62e15 100755
--- a/test/test-exec-deserialization.py
+++ b/test/test-exec-deserialization.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
#
# Copyright 2017 Michal Sekletar <msekleta@redhat.com>
diff --git a/tools/catalog-report.py b/tools/catalog-report.py
index b220060cc8..357e498cdc 100644
--- a/tools/catalog-report.py
+++ b/tools/catalog-report.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd. It is distrubuted under the MIT license, see
diff --git a/tools/gdb-sd_dump_hashmaps.py b/tools/gdb-sd_dump_hashmaps.py
index d20016e005..62ce8006f5 100644
--- a/tools/gdb-sd_dump_hashmaps.py
+++ b/tools/gdb-sd_dump_hashmaps.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd.
diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py
index 8ce09ca2fa..1b287997fa 100755
--- a/tools/make-directive-index.py
+++ b/tools/make-directive-index.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd.
diff --git a/tools/make-man-index.py b/tools/make-man-index.py
index 50ad9532cd..abc33e7394 100755
--- a/tools/make-man-index.py
+++ b/tools/make-man-index.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd.
diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py
index ecb9d2d9b5..e9e39f10af 100644
--- a/tools/make-man-rules.py
+++ b/tools/make-man-rules.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd.
diff --git a/tools/xml_helper.py b/tools/xml_helper.py
index b2c036909d..0088be5bd9 100644
--- a/tools/xml_helper.py
+++ b/tools/xml_helper.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
#
# This file is part of systemd.