--- /dev/null
+custom: ['https://spi-inc.org/projects/systemd/', 'https://www.paypal.com/donate/?token=fBGzXDOyIGobZH3oEhYQlYlA61OMRXVnF9XXQqNNehRs-nliAU5XxozIh9z-hlmE-xXC-m']
--- /dev/null
+You are looking for the traditional text log files in /var/log, and they are
+gone?
+
+Here's an explanation on what's going on:
+
+You are running a systemd-based OS where traditional syslog has been replaced
+with the Journal. The journal stores the same (and more) information as classic
+syslog. To make use of the journal and access the collected log data simply
+invoke "journalctl", which will output the logs in the identical text-based
+format the syslog files in /var/log used to be. For further details, please
+refer to journalctl(1).
+
+Alternatively, consider installing one of the traditional syslog
+implementations available for your distribution, which will generate the
+classic log files for you. Syslog implementations such as syslog-ng or rsyslog
+may be installed side-by-side with the journal and will continue to function
+the way they always did.
+
+Thank you!
+
+Further reading:
+ man:journalctl(1)
+ man:systemd-journald.service(8)
+ man:journald.conf(5)
+ http://0pointer.de/blog/projects/the-journal.html
+++ /dev/null
-You are looking for the traditional text log files in @VARLOGDIR@, and
-they are gone?
-
-Here's an explanation on what's going on:
-
-You are running a systemd-based OS where traditional syslog has been
-replaced with the Journal. The journal stores the same (and more)
-information as classic syslog. To make use of the journal and access
-the collected log data simply invoke "journalctl", which will output
-the logs in the identical text-based format the syslog files in
-@VARLOGDIR@ used to be. For further details, please refer to
-journalctl(1).
-
-Alternatively, consider installing one of the traditional syslog
-implementations available for your distribution, which will generate
-the classic log files for you. Syslog implementations such as
-syslog-ng or rsyslog may be installed side-by-side with the journal
-and will continue to function the way they always did.
-
-Thank you!
-
-Further reading:
- man:journalctl(1)
- man:systemd-journald.service(8)
- man:journald.conf(5)
- http://0pointer.de/blog/projects/the-journal.html
# SPDX-License-Identifier: LGPL-2.1+
-file = configure_file(
- input : 'README.in',
- output : 'README',
- configuration : substs)
-
-if conf.get('HAVE_SYSV_COMPAT') == 1
- install_data(file,
- install_dir : varlogdir)
+if conf.get('HAVE_SYSV_COMPAT') == 1 and get_option('create-log-dirs')
+ install_data('README',
+ install_dir : '/var/log')
endif
sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
+
sensor:modalias:acpi:KXJ2109*:dmi:*:svnASUSTeK*:pnME176C*
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c:*
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
+#########################################
+# Irbis TW90
+#########################################
+sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW90:*
+ ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1
+
#########################################
# iOTA 360
#########################################
<!ENTITY CERTIFICATE_ROOT @CERTIFICATE_ROOT@>
<!ENTITY MEMORY_ACCOUNTING_DEFAULT @MEMORY_ACCOUNTING_DEFAULT_YES_NO@>
<!ENTITY KILL_USER_PROCESSES @KILL_USER_PROCESSES_YES_NO@>
+<!ENTITY DEBUGTTY @DEBUGTTY@>
<?xml version="1.0"?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
+<!ENTITY % entities SYSTEM "custom-entities.ent" >
+%entities;
+]>
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="systemd-debug-generator">
<option>rd.systemd.debug_shell</option> option is
specified, the debug shell service
<literal>debug-shell.service</literal> is pulled into the boot
- transaction. It will spawn a debug shell on tty9 during early
- system startup. Note that the shell may also be turned on
- persistently by enabling it with
+ transaction and a debug shell will be spawned during early boot.
+ By default, <filename>&DEBUGTTY;</filename> is used, but a specific tty can also be set,
+ either with or without the <filename>/dev/</filename> prefix.
+ Note that the shell may also be turned on persistently by enabling it with
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
<command>enable</command> command.
<option>rd.systemd.debug_shell=</option> is honored only by initial
configuration or lifetime guarantees, please consider using
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ <para>The directories defined by these options are always created under the standard paths used by systemd
+ (<filename>/var</filename>, <filename>/run</filename>, <filename>/etc</filename>, …). If the service needs
+ directories in a different location, a different mechanism has to be used to create them.</para>
+
+ <para><citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> provides
+ functionality that overlaps with these options. Using these options is recommended, because the lifetime of
+ the directories is tied directly to the lifetime of the unit, and it is not necessary to ensure that the
+ <filename>tmpfiles.d</filename> configuration is executed before the unit is started.</para>
+
<para>Example: if a system service unit has the following,
<programlisting>RuntimeDirectory=foo/bar baz</programlisting>
the service manager creates <filename>/run/foo</filename> (if it does not exist),
<term><varname>Driver=</varname></term>
<listitem>
<para>A whitespace-separated list of shell-style globs matching the driver currently bound to the
- device, as exposed by the udev property <varname>DRIVER</varname> of its parent device, or if that
+ device, as exposed by the udev property <varname>ID_NET_DRIVER</varname> of its parent device, or if that
is not set, the driver as exposed by <command>ethtool -i</command> of the device itself.</para>
</listitem>
</varlistentry>
property <varname>DEVTYPE</varname>.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>Property=</varname></term>
+ <listitem>
+ <para>A whitespace-separated list of udev property name with its value after a equal
+ (<literal>=</literal>). If multiple properties are specified, the test results are ANDed.
+ If the list is prefixed with a "!", the test is inverted. If a value contains white
+ spaces, then please quote whole key and value pair. If a value contains quotation, then
+ please escape the quotation with <literal>\</literal>.</para>
+
+ <para>Example: if a .link file has the following:
+ <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting>
+ then, the .link file matches only when an interface has all the above three properties.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>Host=</varname></term>
<listitem>
<row><entry><varname>fou</varname></entry>
<entry>Foo-over-UDP tunneling.</entry></row>
+ <row><entry><varname>xfrm</varname></entry>
+ <entry>A virtual tunnel interface like vti/vti6 but with several advantages.</entry></row>
+
</tbody>
</tgroup>
</table>
Linux Ethernet Bonding Driver HOWTO</ulink></para>
</refsect1>
+ <refsect1>
+ <title>[Xfrm] Section Options</title>
+
+ <para>The <literal>[Xfrm]</literal> section accepts the following
+ keys:</para>
+
+ <variablelist class='network-directives'>
+ <varlistentry>
+ <term><varname>InterfaceId=</varname></term>
+ <listitem>
+ <para>Sets the ID/key of the xfrm interface which needs to be associated with a SA/policy.
+ Can be decimal or hexadecimal, valid range is 0-0xffffffff, defaults to 0.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>Independent=</varname></term>
+ <listitem>
+ <para>Takes a boolean. If set to <literal>no</literal>, the xfrm interface should have an
+ underlying device which can be used for hardware offloading. Defaults to <literal>no</literal>.
+ See <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for how to configure the underlying device.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>For more detail information see
+ <ulink url="https://lwn.net/Articles/757391">
+ Virtual xfrm interfaces</ulink></para>
+ </refsect1>
+
<refsect1>
<title>[VRF] Section Options</title>
<para>The <literal>[VRF]</literal> section only applies for
AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24
Endpoint=wireguard.example.com:51820</programlisting>
</example>
+
+ <example>
+ <title>/etc/systemd/network/27-xfrm.netdev</title>
+ <programlisting>[Xfrm]
+Name=xfrm0
+Kind=xfrm
+
+[Xfrm]
+Independent=yes</programlisting>
+ </example>
</refsect1>
<refsect1>
<listitem>
<para>A whitespace-separated list of shell-style globs
matching the driver currently bound to the device, as
- exposed by the udev property <literal>DRIVER</literal>
+ exposed by the udev property <literal>ID_NET_DRIVER</literal>
of its parent device, or if that is not set the driver
as exposed by <literal>ethtool -i</literal> of the
device itself. If the list is prefixed with a "!", the
with a "!", the test is inverted.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>Property=</varname></term>
+ <listitem>
+ <para>A whitespace-separated list of udev property name with its value after a equal
+ (<literal>=</literal>). If multiple properties are specified, the test results are ANDed.
+ If the list is prefixed with a "!", the test is inverted. If a value contains white
+ spaces, then please quote whole key and value pair. If a value contains quotation, then
+ please escape the quotation with <literal>\</literal>.</para>
+
+ <para>Example: if a .network file has the following:
+ <programlisting>Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\""</programlisting>
+ then, the .network file matches only when an interface has all the above three properties.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>Host=</varname></term>
<listitem>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>Xfrm=</varname></term>
+ <listitem>
+ <para>The name of the xfrm to create on the link. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ This option may be specified more than once.</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><varname>KeepConfiguration=</varname></term>
<listitem>
MACVTAP=macvtap-test
</programlisting>
</example>
+
+ <example>
+ <title>A Xfrm interface with physical underlying device.</title>
+
+ <programlisting># /etc/systemd/network/27-xfrm.netdev
+[NetDev]
+Name=xfrm0
+
+[Xfrm]
+InterfaceId=7</programlisting>
+
+ <programlisting># /etc/systemd/network/27-eth0.network
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm0</programlisting>
+
+ <para>This creates a <literal>xfrm0</literal> interface and binds it to the <literal>eth0</literal> device.
+ This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
+ If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
+ </para>
+ </example>
</refsect1>
<refsect1>
lines, when omitted or when set to <literal>-</literal>, the file ownership will not be modified. These
parameters are ignored for <varname>x</varname>, <varname>r</varname>, <varname>R</varname>,
<varname>L</varname>, <varname>t</varname>, and <varname>a</varname> lines.</para>
+
+ <para>This field should generally only reference system users/groups, i.e. users/groups that are
+ guaranteed to be resolvable during early boot. If this field references users/groups that only become
+ resolveable during later boot (i.e. after NIS, LDAP or a similar networked directory service become
+ available), execution of the operations declared by the line will likely fail. Also see <ulink
+ url="https://systemd.io/UIDS-GIDS.html#notes-on-resolvability-of-user-and-group-names">Notes on
+ Resolvability of User and Group Names</ulink> for more information on requirements on system user/group
+ definitions.</para>
</refsect2>
<refsect2>
polkitpolicydir = join_paths(datadir, 'polkit-1/actions')
polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d')
polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d')
-varlogdir = join_paths(localstatedir, 'log')
xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d')
rpmmacrosdir = get_option('rpmmacrosdir')
if rpmmacrosdir != 'no'
substs.set('userenvgeneratordir', userenvgeneratordir)
substs.set('systemshutdowndir', systemshutdowndir)
substs.set('systemsleepdir', systemsleepdir)
-substs.set('VARLOGDIR', varlogdir)
substs.set('CERTIFICATEROOT', get_option('certificate-root'))
substs.set('SYSTEMCTL', join_paths(rootbindir, 'systemctl'))
substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed'))
substs.set('SUSHELL', get_option('debug-shell'))
substs.set('DEBUGTTY', get_option('debug-tty'))
+conf.set_quoted('DEBUGTTY', get_option('debug-tty'))
enable_debug_hashmap = false
enable_debug_mmap_cache = false
meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
includes = include_directories('src/basic',
+ 'src/boot',
'src/shared',
'src/systemd',
'src/journal',
description : 'install the systemd-timesyncd daemon')
option('remote', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'support for "journal over the network"')
+option('create-log-dirs', type : 'boolean',
+ description : 'create /var/log/journal{,/remote}')
option('nss-myhostname', type : 'boolean',
description : 'install nss-myhostname module')
option('nss-mymachines', type : 'combo', choices : ['auto', 'true', 'false'],
sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
# wait until online
while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
-apt-get -q update
+apt-get -q --allow-releaseinfo-change update
apt-get -y dist-upgrade
apt-get install -y eatmydata
EOF
if (t->kernel_done_time > 0)
strpcpyf(&ptr, size, "= %s ", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC));
- if (unit_id && activated_time > 0 && activated_time != USEC_INFINITY) {
+ if (unit_id && timestamp_is_set(activated_time)) {
usec_t base = t->userspace_time > 0 ? t->userspace_time : t->reverse_offset;
size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id,
assert(ret);
+ if (major(d) == 0)
+ return -ENODEV;
+
/* If it has a queue this is good enough for us */
xsprintf_sys_block_path(p, "/queue", d);
if (access(p, F_OK) >= 0) {
/* If it is a partition find the originating device */
xsprintf_sys_block_path(p, "/partition", d);
if (access(p, F_OK) < 0)
- return -ENOENT;
+ return -errno;
/* Get parent dev_t */
xsprintf_sys_block_path(p, "/../dev", d);
/* Only return this if it is really good enough for us. */
xsprintf_sys_block_path(p, "/queue", devt);
if (access(p, F_OK) < 0)
- return -ENOENT;
+ return -errno;
*ret = devt;
- return 0;
+ return 1;
}
int get_block_device(const char *path, dev_t *dev) {
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include <stdlib.h>
+#include <string.h>
+
#include "macro.h"
static inline void _reset_errno_(int *saved_errno) {
return -errno;
}
+static inline char *strerror_safe(int error) {
+ /* 'safe' here does NOT mean thread safety. */
+ return strerror(abs(error));
+}
+
/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5.
*
* Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the
e = getenv("SYSTEMD_LOG_COLOR");
if (e && log_show_color_from_string(e) < 0)
- log_warning("Failed to parse bool '%s'. Ignoring.", e);
+ log_warning("Failed to parse log color '%s'. Ignoring.", e);
e = getenv("SYSTEMD_LOG_LOCATION");
if (e && log_show_location_from_string(e) < 0)
- log_warning("Failed to parse bool '%s'. Ignoring.", e);
+ log_warning("Failed to parse log location '%s'. Ignoring.", e);
}
LogTarget log_get_target(void) {
#pragma once
#include <inttypes.h>
+#include <malloc.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
void *explicit_bzero_safe(void *p, size_t l);
#endif
+static inline void erase_and_freep(void *p) {
+ void *ptr = *(void**) p;
+
+ if (ptr) {
+ size_t l = malloc_usable_size(ptr);
+ explicit_bzero_safe(ptr, l);
+ free(ptr);
+ }
+}
+
/* Use with _cleanup_ to erase a single 'char' when leaving scope */
static inline void erase_char(char *p) {
explicit_bzero_safe(p, sizeof(char));
assert(buf);
- if (l <
- 3 + /* week day */
- 1 + 10 + /* space and date */
- 1 + 8 + /* space and time */
- (us ? 1 + 6 : 0) + /* "." and microsecond part */
- 1 + 1 + /* space and shortest possible zone */
- 1)
+ if (l < (size_t) (3 + /* week day */
+ 1 + 10 + /* space and date */
+ 1 + 8 + /* space and time */
+ (us ? 1 + 6 : 0) + /* "." and microsecond part */
+ 1 + 1 + /* space and shortest possible zone */
+ 1))
return NULL; /* Not enough space even for the shortest form. */
if (t <= 0 || t == USEC_INFINITY)
return NULL; /* Timestamp is unset */
#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \
IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
+static inline bool timestamp_is_set(usec_t timestamp) {
+ return timestamp > 0 && timestamp != USEC_INFINITY;
+}
+
static inline bool dual_timestamp_is_set(const dual_timestamp *ts) {
- return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
- (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
+ return timestamp_is_set(ts->realtime) ||
+ timestamp_is_set(ts->monotonic);
}
static inline bool triple_timestamp_is_set(const triple_timestamp *ts) {
- return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
- (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
- (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
+ return timestamp_is_set(ts->realtime) ||
+ timestamp_is_set(ts->monotonic) ||
+ timestamp_is_set(ts->boottime);
}
usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
uint64_t flag;
const char *name;
} flags[] = {
- { EFI_LOADER_FEATURE_BOOT_COUNTING, "Boot counting" },
- { EFI_LOADER_FEATURE_CONFIG_TIMEOUT, "Menu timeout control" },
- { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control" },
- { EFI_LOADER_FEATURE_ENTRY_DEFAULT, "Default entry control" },
- { EFI_LOADER_FEATURE_ENTRY_ONESHOT, "One-shot entry control" },
+ { EFI_LOADER_FEATURE_BOOT_COUNTING, "Boot counting" },
+ { EFI_LOADER_FEATURE_CONFIG_TIMEOUT, "Menu timeout control" },
+ { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control" },
+ { EFI_LOADER_FEATURE_ENTRY_DEFAULT, "Default entry control" },
+ { EFI_LOADER_FEATURE_ENTRY_ONESHOT, "One-shot entry control" },
+ { EFI_LOADER_FEATURE_XBOOTLDR, "Support for XBOOTLDR partition" },
};
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
#include "disk.h"
#include "graphics.h"
#include "linux.h"
+#include "loader-features.h"
#include "measure.h"
#include "pe.h"
#include "shim.h"
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
static const UINT64 loader_features =
- (1ULL << 0) | /* I honour the LoaderConfigTimeout variable */
- (1ULL << 1) | /* I honour the LoaderConfigTimeoutOneShot variable */
- (1ULL << 2) | /* I honour the LoaderEntryDefault variable */
- (1ULL << 3) | /* I honour the LoaderEntryOneShot variable */
- (1ULL << 4) | /* I support boot counting */
+ EFI_LOADER_FEATURE_CONFIG_TIMEOUT |
+ EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT |
+ EFI_LOADER_FEATURE_ENTRY_DEFAULT |
+ EFI_LOADER_FEATURE_ENTRY_ONESHOT |
+ EFI_LOADER_FEATURE_BOOT_COUNTING |
+ EFI_LOADER_FEATURE_XBOOTLDR |
0;
_cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#ifndef UINT64_C
+# define UINT64_C(c) (c ## ULL)
+#endif
+
+#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT (UINT64_C(1) << 0)
+#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1)
+#define EFI_LOADER_FEATURE_ENTRY_DEFAULT (UINT64_C(1) << 2)
+#define EFI_LOADER_FEATURE_ENTRY_ONESHOT (UINT64_C(1) << 3)
+#define EFI_LOADER_FEATURE_BOOT_COUNTING (UINT64_C(1) << 4)
+#define EFI_LOADER_FEATURE_XBOOTLDR (UINT64_C(1) << 5)
cmd = exec_command_line(c->argv);
fprintf(f,
"%sCommand Line: %s\n",
- prefix, cmd ? cmd : strerror(ENOMEM));
+ prefix, cmd ? cmd : strerror_safe(ENOMEM));
exec_status_dump(&c->exec_status, f, prefix2);
}
if (j->unit->job_timeout != USEC_INFINITY)
timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
- if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
+ if (timestamp_is_set(j->begin_running_usec))
timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
if (timeout_time == USEC_INFINITY)
log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device);
}
- if (arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
+ if (timestamp_is_set(arg_runtime_watchdog))
watchdog_set_timeout(&arg_runtime_watchdog);
}
assert(f);
for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) {
- char buf[FORMAT_TIMESTAMP_MAX];
+ const dual_timestamp *t = m->timestamps + q;
+ char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
- if (dual_timestamp_is_set(m->timestamps + q))
+ if (dual_timestamp_is_set(t))
fprintf(f, "%sTimestamp %s: %s\n",
strempty(prefix),
manager_timestamp_to_string(q),
- format_timestamp(buf, sizeof(buf), m->timestamps[q].realtime));
+ timestamp_is_set(t->realtime) ? format_timestamp(buf, sizeof buf, t->realtime) :
+ format_timespan(buf, sizeof buf, t->monotonic, 1));
}
manager_dump_units(m, f, prefix);
while (m->objective == MANAGER_OK) {
usec_t wait_usec;
- if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m))
+ if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m))
watchdog_ping();
if (!ratelimit_below(&rl)) {
continue;
/* Sleep for half the watchdog time */
- if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m)) {
+ if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m)) {
wait_usec = m->runtime_watchdog / 2;
if (wait_usec <= 0)
wait_usec = 1;
break;
}
- r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror(-r));
+ r = log_warning_errno(errno, "Failed to add watch on %s: %s", s->path, errno == ENOSPC ? "too many watches" : strerror_safe(r));
if (cut)
*cut = tmp;
goto fail;
#include "alloc-util.h"
#include "audit-fd.h"
#include "bus-util.h"
+#include "errno-util.h"
#include "format-util.h"
#include "log.h"
#include "path-util.h"
/* Return an access denied error, if we couldn't load
* the AVC but enforcing mode was on, or we couldn't
* determine whether it is one. */
- return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror(saved_errno));
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror_safe(saved_errno));
}
selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
return log_oom();
n = strlen(e);
- if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1))
+ if (!GREEDY_REALLOC(args, allocated, length + 2 + n + 2))
return log_oom();
if (length > 0)
args[length++] = ' ';
+ args[length++] = '"';
memcpy(args + length, e, n);
length += n;
+ args[length++] = '"';
}
if (!GREEDY_REALLOC(args, allocated, length + 1))
for (;;) {
_cleanup_free_ char *arg = NULL;
- r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE);
+ r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE);
if (r < 0)
return r;
if (r == 0)
r = socket_address_print(&p->address, &k);
if (r < 0)
- t = strerror(-r);
+ t = strerror_safe(r);
else
t = k;
"%s\tMerged into: %s\n",
prefix, u->merged_into->id);
else if (u->load_state == UNIT_ERROR)
- fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
+ fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error));
for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track))
fprintf(f, "%s\tBus Ref: %s\n", prefix, n);
log_setup_service();
+ crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL);
+ if (DEBUG_LOGGING)
+ /* libcryptsetup won't even consider debug messages by default */
+ crypt_set_debug_level(CRYPT_DEBUG_ALL);
+
umask(0022);
if (streq(argv[1], "attach")) {
#include <unistd.h>
#include "alloc-util.h"
+#include "dropin.h"
#include "generator.h"
#include "mkdir.h"
#include "parse-util.h"
static char *arg_default_unit = NULL;
static char **arg_mask = NULL;
static char **arg_wants = NULL;
-static bool arg_debug_shell = false;
+static char *arg_debug_shell = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_default_unit, freep);
STATIC_DESTRUCTOR_REGISTER(arg_mask, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_wants, strv_freep);
+STATIC_DESTRUCTOR_REGISTER(arg_debug_shell, freep);
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
int r;
return log_oom();
} else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) {
+ const char *t = NULL;
- if (value) {
- r = parse_boolean(value);
- if (r < 0)
- log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value);
- else
- arg_debug_shell = r;
- } else
- arg_debug_shell = true;
+ r = value ? parse_boolean(value) : 1;
+ if (r < 0)
+ t = skip_dev_prefix(value);
+ else if (r > 0)
+ t = skip_dev_prefix(DEBUGTTY);
+
+ if (free_and_strdup(&arg_debug_shell, t) < 0)
+ return log_oom();
} else if (streq(key, "systemd.unit")) {
return r;
}
+static void install_debug_shell_dropin(const char *dir) {
+ int r;
+
+ if (streq(arg_debug_shell, skip_dev_prefix(DEBUGTTY)))
+ return;
+
+ r = write_drop_in_format(dir, "debug-shell.service", 50, "tty",
+ "[Unit]\n"
+ "Description=Early root shell on /dev/%s FOR DEBUGGING ONLY\n"
+ "ConditionPathExists=\n"
+ "[Service]\n"
+ "TTYPath=/dev/%s",
+ arg_debug_shell, arg_debug_shell);
+ if (r < 0)
+ log_warning_errno(r, "Failed to write drop-in for debug-shell.service, ignoring: %m");
+}
+
static int run(const char *dest, const char *dest_early, const char *dest_late) {
int r, q;
r = strv_extend(&arg_wants, "debug-shell.service");
if (r < 0)
return log_oom();
+
+ install_debug_shell_dropin(arg_dest);
}
r = generate_mask_symlinks();
#include "device-util.h"
#include "fd-util.h"
#include "fs-util.h"
+#include "fsck-util.h"
#include "main-func.h"
#include "parse-util.h"
#include "path-util.h"
#include "stdio-util.h"
#include "util.h"
-/* exit codes as defined in fsck(8) */
-enum {
- FSCK_SUCCESS = 0,
- FSCK_ERROR_CORRECTED = 1 << 0,
- FSCK_SYSTEM_SHOULD_REBOOT = 1 << 1,
- FSCK_ERRORS_LEFT_UNCORRECTED = 1 << 2,
- FSCK_OPERATIONAL_ERROR = 1 << 3,
- FSCK_USAGE_OR_SYNTAX_ERROR = 1 << 4,
- FSCK_USER_CANCELLED = 1 << 5,
- FSCK_SHARED_LIB_ERROR = 1 << 7,
-};
-
static bool arg_skip = false;
static bool arg_force = false;
static bool arg_show_progress = false;
static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
CurlGlue *g = userdata;
- int action, k = 0, translated_fd;
+ int action, k = 0;
assert(s);
assert(g);
- translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
-
if (FLAGS_SET(revents, EPOLLIN | EPOLLOUT))
action = CURL_POLL_INOUT;
else if (revents & EPOLLIN)
else
action = 0;
- if (curl_multi_socket_action(g->curl, translated_fd, action, &k) != CURLM_OK)
+ if (curl_multi_socket_action(g->curl, fd, action, &k) != CURLM_OK)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to propagate IO event.");
}
static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
- sd_event_source *io;
+ sd_event_source *io = socketp;
CurlGlue *g = userdata;
uint32_t events = 0;
int r;
assert(curl);
assert(g);
- io = hashmap_get(g->ios, FD_TO_PTR(s));
-
if (action == CURL_POLL_REMOVE) {
if (io) {
- int fd;
-
- fd = sd_event_source_get_io_fd(io);
- assert(fd >= 0);
-
sd_event_source_disable_unref(io);
hashmap_remove(g->ios, FD_TO_PTR(s));
- hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
-
- safe_close(fd);
}
return 0;
return -1;
}
- r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
- if (r < 0) {
- log_oom();
- return -1;
- }
-
if (action == CURL_POLL_IN)
events = EPOLLIN;
else if (action == CURL_POLL_OUT)
if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
return -1;
} else {
- _cleanup_close_ int fd = -1;
-
- /* When curl needs to remove an fd from us it closes
- * the fd first, and only then calls into us. This is
- * nasty, since we cannot pass the fd on to epoll()
- * anymore. Hence, duplicate the fds here, and keep a
- * copy for epoll which we control after use. */
-
- fd = fcntl(s, F_DUPFD_CLOEXEC, 3);
- if (fd < 0)
+ if (sd_event_add_io(g->event, &io, s, events, curl_glue_on_io, g) < 0)
return -1;
- if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
+ if (curl_multi_assign(g->curl, s, io) != CURLM_OK)
return -1;
(void) sd_event_source_set_description(io, "curl-io");
sd_event_source_unref(io);
return -1;
}
-
- r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
- if (r < 0) {
- log_oom();
- hashmap_remove(g->ios, FD_TO_PTR(s));
- sd_event_source_unref(io);
- return -1;
- }
-
- fd = -1;
}
return 0;
curl_multi_cleanup(g->curl);
while ((io = hashmap_steal_first(g->ios))) {
- int fd;
-
- fd = sd_event_source_get_io_fd(io);
- assert(fd >= 0);
-
- hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
-
- safe_close(fd);
sd_event_source_unref(io);
}
CURLM *curl;
sd_event_source *timer;
Hashmap *ios;
- Hashmap *translate_fds;
void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code);
void *userdata;
#include "alloc-util.h"
#include "bus-util.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "hostname-util.h"
errno = 0;
k = fread(buf, 1, n, m->tmp);
if (k != n) {
- log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
+ log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
return MHD_CONTENT_READER_END_WITH_ERROR;
}
errno = 0;
k = fread(buf, 1, n, m->tmp);
if (k != n) {
- log_error("Failed to read from file: %s", errno ? strerror(errno) : "Premature EOF");
+ log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF");
return MHD_CONTENT_READER_END_WITH_ERROR;
}
install_data('browse.html',
install_dir : join_paths(pkgdatadir, 'gatewayd'))
- meson.add_install_script('sh', '-c',
- mkdir_p.format('/var/log/journal/remote'))
- meson.add_install_script('sh', '-c',
- '''chown 0:0 $DESTDIR/var/log/journal/remote &&
- chmod 755 $DESTDIR/var/log/journal/remote || :''')
+ if get_option('create-log-dirs')
+ meson.add_install_script('sh', '-c',
+ mkdir_p.format('/var/log/journal/remote'))
+ meson.add_install_script('sh', '-c',
+ '''chown 0:0 $DESTDIR/var/log/journal/remote &&
+ chmod 755 $DESTDIR/var/log/journal/remote || :''')
+ endif
endif
r = get_boots(j, NULL, &boot_id, arg_boot_offset);
assert(r <= 1);
if (r <= 0) {
- const char *reason = (r == 0) ? "No such boot ID in journal" : strerror(-r);
+ const char *reason = (r == 0) ? "No such boot ID in journal" : strerror_safe(r);
if (sd_id128_is_null(arg_boot_id))
log_error("Data from the specified boot (%+i) is not available: %s",
/* We failed to format the message. Emit a warning instead. */
char buf[LINE_MAX];
- xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r));
+ xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror_safe(r));
n = 3;
iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=4");
install_data('journald.conf',
install_dir : pkgsysconfdir)
-meson.add_install_script(
- 'sh', '-c',
- mkdir_p.format('/var/log/journal'))
-meson.add_install_script(
- 'sh', '-c',
- '''chown 0:0 $DESTDIR/var/log/journal &&
- chmod 755 $DESTDIR/var/log/journal || :''')
-if get_option('adm-group')
+if get_option('create-log-dirs')
meson.add_install_script(
'sh', '-c',
- 'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :')
-endif
-if get_option('wheel-group')
+ mkdir_p.format('/var/log/journal'))
meson.add_install_script(
'sh', '-c',
- 'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :')
+ '''chown 0:0 $DESTDIR/var/log/journal &&
+ chmod 755 $DESTDIR/var/log/journal || :''')
+ if get_option('adm-group')
+ meson.add_install_script(
+ 'sh', '-c',
+ 'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :')
+ endif
+ if get_option('wheel-group')
+ meson.add_install_script(
+ 'sh', '-c',
+ 'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :')
+ endif
endif
#include "conf-parser.h"
#include "device-util.h"
#include "dhcp-lease-internal.h"
+#include "env-util.h"
#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
return 0;
}
-static bool net_condition_test_strv(char * const *raw_patterns,
- const char *string) {
- if (strv_isempty(raw_patterns))
+static bool net_condition_test_strv(char * const *patterns, const char *string) {
+ char * const *p;
+ bool match = false, has_positive_rule = false;
+
+ if (strv_isempty(patterns))
return true;
- /* If the patterns begin with "!", edit it out and negate the test. */
- if (raw_patterns[0][0] == '!') {
- char **patterns;
- size_t i, length;
+ STRV_FOREACH(p, patterns) {
+ const char *q = *p;
+ bool invert;
+
+ invert = *q == '!';
+ q += invert;
+
+ if (!invert)
+ has_positive_rule = true;
+
+ if (string && fnmatch(q, string, 0) == 0) {
+ if (invert)
+ return false;
+ else
+ match = true;
+ }
+ }
+
+ return has_positive_rule ? match : true;
+}
+
+static int net_condition_test_property(char * const *match_property, sd_device *device) {
+ char * const *p;
+
+ if (strv_isempty(match_property))
+ return true;
+
+ STRV_FOREACH(p, match_property) {
+ _cleanup_free_ char *key = NULL;
+ const char *val, *dev_val;
+ bool invert, v;
+
+ invert = **p == '!';
+
+ val = strchr(*p + invert, '=');
+ if (!val)
+ return -EINVAL;
+
+ key = strndup(*p + invert, val - *p - invert);
+ if (!key)
+ return -ENOMEM;
+
+ val++;
- length = strv_length(raw_patterns) + 1; /* Include the NULL. */
- patterns = newa(char*, length);
- patterns[0] = raw_patterns[0] + 1; /* Skip the "!". */
- for (i = 1; i < length; i++)
- patterns[i] = raw_patterns[i];
+ v = device &&
+ sd_device_get_property_value(device, key, &dev_val) >= 0 &&
+ fnmatch(val, dev_val, 0) == 0;
- return !string || !strv_fnmatch(patterns, string, 0);
+ if (invert ? v : !v)
+ return false;
}
- return string && strv_fnmatch(raw_patterns, string, 0);
+ return true;
}
bool net_match_config(Set *match_mac,
char * const *match_drivers,
char * const *match_types,
char * const *match_names,
+ char * const *match_property,
+ sd_device *device,
const struct ether_addr *dev_mac,
- const char *dev_path,
- const char *dev_driver,
- const char *dev_type,
const char *dev_name) {
+ const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str;
+
+ if (device) {
+ (void) sd_device_get_property_value(device, "ID_PATH", &dev_path);
+ (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver);
+ (void) sd_device_get_devtype(device, &dev_type);
+
+ if (!dev_name)
+ (void) sd_device_get_sysname(device, &dev_name);
+ if (!dev_mac &&
+ sd_device_get_sysattr_value(device, "address", &mac_str) >= 0)
+ dev_mac = ether_aton(mac_str);
+ }
+
if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
return false;
if (!net_condition_test_strv(match_names, dev_name))
return false;
+ if (!net_condition_test_property(match_property, device))
+ return false;
+
return true;
}
return 0;
}
-int config_parse_ifnames(
+int config_parse_match_strv(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
+ const char *p = rvalue;
char ***sv = data;
+ bool invert;
int r;
assert(filename);
assert(rvalue);
assert(data);
+ if (isempty(rvalue)) {
+ *sv = strv_free(*sv);
+ return 0;
+ }
+
+ invert = *p == '!';
+ p += invert;
+
for (;;) {
- _cleanup_free_ char *word = NULL;
+ _cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, 0);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
+}
+
+int config_parse_match_ifnames(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
- break;
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Failed to parse interface name list: %s", rvalue);
+ return 0;
+ }
if (!ifname_valid(word)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue);
- return 0;
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Interface name is not valid or too long, ignoring assignment: %s", word);
+ continue;
}
- r = strv_push(sv, word);
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
if (r < 0)
return log_oom();
-
- word = NULL;
}
+}
- return 0;
+int config_parse_match_property(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *p = rvalue;
+ char ***sv = data;
+ bool invert;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ invert = *p == '!';
+ p += invert;
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL, *k = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == 0)
+ return 0;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (!env_assignment_is_valid(word)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid property or value, ignoring assignment: %s", word);
+ continue;
+ }
+
+ if (invert) {
+ k = strjoin("!", word);
+ if (!k)
+ return log_oom();
+ } else
+ k = TAKE_PTR(word);
+
+ r = strv_consume(sv, TAKE_PTR(k));
+ if (r < 0)
+ return log_oom();
+ }
}
int config_parse_ifalias(const char *unit,
char * const *match_driver,
char * const *match_type,
char * const *match_name,
+ char * const *match_property,
+ sd_device *device,
const struct ether_addr *dev_mac,
- const char *dev_path,
- const char *dev_driver,
- const char *dev_type,
const char *dev_name);
CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
-CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_match_property);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
assert(client);
if (error < 0)
- log_dhcp_client(client, "STOPPED: %s", strerror(-error));
+ log_dhcp_client_errno(client, error, "STOPPED: %m");
else if (error == SD_DHCP_CLIENT_EVENT_STOP)
log_dhcp_client(client, "STOPPED");
else
r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
lease->dns_count,
&lease->dns_allocated);
- if (r < 0) {
- log_dhcp6_client(client, "Invalid DNS server option: %s",
- strerror(-r));
-
- return r;
- }
+ if (r < 0)
+ return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m");
lease->dns_count = r;
r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
lease->ntp_count,
&lease->ntp_allocated);
- if (r < 0) {
- log_dhcp6_client(client, "Invalid SNTP server option: %s",
- strerror(-r));
-
- return r;
- }
+ if (r < 0)
+ return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m");
lease->ntp_count = r;
if (error < 0)
error = -error;
- return strerror(error);
+ return strerror_safe(error);
}
static bool map_ok(const sd_bus_error_map *map) {
#include "bus-internal.h"
#include "bus-match.h"
#include "bus-util.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "format-util.h"
#include "log.h"
errno = 0;
if (read(pp[0], &x, 1) <= 0) {
- log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
+ log_error("Failed to read from pipe: %s", errno != 0 ? strerror_safe(errno) : "early read");
goto finish;
}
#include "bus-error.h"
#include "bus-util.h"
#include "errno-list.h"
+#include "errno-util.h"
static void test_error(void) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
assert_se(!sd_bus_error_is_set(&error));
assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
assert_se(streq(error.name, "System.Error.EBUSY"));
- assert_se(streq(error.message, strerror(EBUSY)));
+ assert_se(streq(error.message, strerror_safe(EBUSY)));
assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
assert_se(sd_bus_error_get_errno(&error) == EBUSY);
assert_se(sd_bus_error_is_set(&error));
#include "signal-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "strxcpyx.h"
#include "time-util.h"
#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC)
}
static void event_log_delays(sd_event *e) {
- char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1];
- unsigned i;
- int o;
+ char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p;
+ size_t l, i;
- for (i = o = 0; i < ELEMENTSOF(e->delays); i++) {
- o += snprintf(&b[o], sizeof(b) - o, "%u ", e->delays[i]);
+ p = b;
+ l = sizeof(b);
+ for (i = 0; i < ELEMENTSOF(e->delays); i++) {
+ l = strpcpyf(&p, l, "%u ", e->delays[i]);
e->delays[i] = 0;
}
- log_debug("Event loop iterations: %.*s", o, b);
+ log_debug("Event loop iterations: %s", b);
}
_public_ int sd_event_run(sd_event *e, uint64_t timeout) {
static int netlink_container_parse(sd_netlink_message *m,
struct netlink_container *container,
- int count,
struct rtattr *rta,
unsigned rt_len) {
_cleanup_free_ struct netlink_attribute *attributes = NULL;
-
- attributes = new0(struct netlink_attribute, count);
- if (!attributes)
- return -ENOMEM;
+ size_t n_allocated = 0;
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
unsigned short type;
type = RTA_TYPE(rta);
- /* if the kernel is newer than the headers we used
- when building, we ignore out-of-range attributes */
- if (type >= count)
- continue;
+ if (!GREEDY_REALLOC0(attributes, n_allocated, type + 1))
+ return -ENOMEM;
if (attributes[type].offset != 0)
log_debug("rtnl: message parse - overwriting repeated attribute");
}
container->attributes = TAKE_PTR(attributes);
- container->n_attributes = count;
+ container->n_attributes = n_allocated;
return 0;
}
r = netlink_message_read_internal(m, type_id, &container, NULL);
if (r < 0)
return r;
- else
- size = (size_t)r;
+
+ size = (size_t)r;
m->n_containers++;
r = netlink_container_parse(m,
&m->containers[m->n_containers],
- type_system_get_count(type_system),
container,
size);
if (r < 0) {
return 0;
}
+int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) {
+ void *container;
+ size_t size;
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
+
+ r = netlink_message_read_internal(m, type_id, &container, NULL);
+ if (r < 0)
+ return r;
+
+ size = (size_t) r;
+
+ m->n_containers++;
+
+ r = netlink_container_parse(m,
+ &m->containers[m->n_containers],
+ container,
+ size);
+ if (r < 0) {
+ m->n_containers--;
+ return r;
+ }
+
+ m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
+
+ return 0;
+}
+
int sd_netlink_message_exit_container(sd_netlink_message *m) {
assert_return(m, -EINVAL);
assert_return(m->sealed, -EINVAL);
r = netlink_container_parse(m,
&m->containers[m->n_containers],
- type_system_get_count(type_system),
(struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
NLMSG_PAYLOAD(m->hdr, size));
if (r < 0)
/* check that the size matches the message type */
if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
- log_debug("sd-netlink: message larger than expected, dropping");
+ log_debug("sd-netlink: message is shorter than expected, dropping");
continue;
}
[IFLA_MACSEC_VALIDATION] = { .type = NETLINK_TYPE_U8 },
};
+static const NLType rtnl_link_info_data_xfrm_types[] = {
+ [IFLA_XFRM_LINK] = { .type = NETLINK_TYPE_U32 },
+ [IFLA_XFRM_IF_ID] = { .type = NETLINK_TYPE_U32 }
+};
+
/* these strings must match the .kind entries in the kernel */
static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_BOND] = "bond",
[NL_UNION_LINK_INFO_DATA_CAN] = "can",
[NL_UNION_LINK_INFO_DATA_MACSEC] = "macsec",
[NL_UNION_LINK_INFO_DATA_NLMON] = "nlmon",
+ [NL_UNION_LINK_INFO_DATA_XFRM] = "xfrm",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
.types = rtnl_link_info_data_can_types },
[NL_UNION_LINK_INFO_DATA_MACSEC] = { .count = ELEMENTSOF(rtnl_link_info_data_macsec_types),
.types = rtnl_link_info_data_macsec_types },
+ [NL_UNION_LINK_INFO_DATA_XFRM] = { .count = ELEMENTSOF(rtnl_link_info_data_xfrm_types),
+ .types = rtnl_link_info_data_xfrm_types },
};
static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
.types = genl_wireguard_cmds,
};
+static const NLType genl_mcast_group_types[] = {
+ [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NETLINK_TYPE_STRING },
+ [CTRL_ATTR_MCAST_GRP_ID] = { .type = NETLINK_TYPE_U32 },
+};
+
+static const NLTypeSystem genl_mcast_group_type_system = {
+ .count = ELEMENTSOF(genl_mcast_group_types),
+ .types = genl_mcast_group_types,
+};
+
static const NLType genl_get_family_types[] = {
- [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING },
- [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 },
+ [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING },
+ [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 },
+ [CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_mcast_group_type_system },
};
static const NLTypeSystem genl_get_family_type_system = {
NL_UNION_LINK_INFO_DATA_CAN,
NL_UNION_LINK_INFO_DATA_MACSEC,
NL_UNION_LINK_INFO_DATA_NLMON,
+ NL_UNION_LINK_INFO_DATA_XFRM,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
#include <net/if.h>
#include <netinet/ether.h>
+#include <linux/genetlink.h>
#include "sd-netlink.h"
#include "missing.h"
#include "netlink-util.h"
#include "socket-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "util.h"
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
}
+static void test_array(void) {
+ _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+
+ assert_se(sd_genl_socket_open(&genl) >= 0);
+ assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
+
+ assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
+ for (unsigned i = 0; i < 10; i++) {
+ char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
+ uint32_t id = i + 1000;
+
+ xsprintf(name, "hoge%" PRIu32, id);
+ assert_se(sd_netlink_message_open_array(m, i + 1) >= 0);
+ assert_se(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id) >= 0);
+ assert_se(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name) >= 0);
+ assert_se(sd_netlink_message_close_container(m) >= 0);
+ }
+ assert_se(sd_netlink_message_close_container(m) >= 0);
+
+ rtnl_message_seal(m);
+ assert_se(sd_netlink_message_rewind(m) >= 0);
+
+ assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
+ for (unsigned i = 0; i < 10; i++) {
+ char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
+ const char *name;
+ uint32_t id;
+
+ assert_se(sd_netlink_message_enter_array(m, i + 1) >= 0);
+ assert_se(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id) >= 0);
+ assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name) >= 0);
+ assert_se(sd_netlink_message_exit_container(m) >= 0);
+
+ assert_se(id == i + 1000);
+ xsprintf(expected, "hoge%" PRIu32, id);
+ assert_se(streq(name, expected));
+ }
+ assert_se(sd_netlink_message_exit_container(m) >= 0);
+
+}
+
int main(void) {
sd_netlink *rtnl;
sd_netlink_message *m;
test_route(rtnl);
test_message(rtnl);
test_container(rtnl);
+ test_array();
if_loopback = (int) if_nametoindex("lo");
assert_se(if_loopback > 0);
#include "sd-messages.h"
#include "alloc-util.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
k = read(s->manager->console_active_fd, t, sizeof(t)-1);
if (k <= 0) {
- log_error("Failed to read current console: %s", k < 0 ? strerror(errno) : "EOF");
+ log_error("Failed to read current console: %s", k < 0 ? strerror_safe(errno) : "EOF");
return k < 0 ? -errno : -EIO;
}
user-runtime-dir.c
'''.split())
+pam_systemd_sym = 'src/login/pam_systemd.sym'
+pam_systemd_c = files('pam_systemd.c')
+
if conf.get('ENABLE_LOGIND') == 1
logind_conf = configure_file(
input : 'logind.conf.in',
install_data(logind_conf,
install_dir : pkgsysconfdir)
- pam_systemd_sym = 'src/login/pam_systemd.sym'
- pam_systemd_c = files('pam_systemd.c')
-
install_data('org.freedesktop.login1.conf',
install_dir : dbuspolicydir)
install_data('org.freedesktop.login1.service',
#include "bus-internal.h"
#include "bus-util.h"
#include "cgroup-util.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
if (streq(limit, "infinity")) {
r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return r;
}
} else {
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U));
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return r;
}
} else {
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return r;
}
} else
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return r;
}
} else
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", field, "t", val);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return r;
}
} else if (streq(field, "CPUWeight"))
* up properly for us. */
if (lstat(path, &st) < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno));
+ pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror_safe(errno));
goto fail;
}
r = sd_bus_open_system(&bus);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r));
return PAM_SESSION_ERR;
}
"org.freedesktop.login1.Manager",
"CreateSession");
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror_safe(r));
return PAM_SESSION_ERR;
}
remote_user,
remote_host);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r));
return PAM_SESSION_ERR;
}
r = sd_bus_message_open_container(m, 'a', "(sv)");
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror_safe(r));
return PAM_SYSTEM_ERR;
}
r = sd_bus_message_close_container(m);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror_safe(r));
return PAM_SYSTEM_ERR;
}
&vtnr,
&existing);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror_safe(r));
return PAM_SESSION_ERR;
}
r = sd_bus_open_system(&bus);
if (r < 0) {
- pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror(-r));
+ pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r));
return PAM_SESSION_ERR;
}
-/***
- SPDX-License-Identifier: LGPL-2.1+
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
{
global:
netdev/l2tp-tunnel.h
netdev/macsec.c
netdev/macsec.h
+ netdev/xfrm.c
+ netdev/xfrm.h
networkd-address-label.c
networkd-address-label.h
networkd-address-pool.c
networkd-can.h
networkd-conf.c
networkd-conf.h
+ networkd-dhcp-common.c
+ networkd-dhcp-common.h
+ networkd-dhcp-server.c
+ networkd-dhcp-server.h
networkd-dhcp4.c
+ networkd-dhcp4.h
networkd-dhcp6.c
+ networkd-dhcp6.h
networkd-fdb.c
networkd-fdb.h
networkd-ipv4ll.c
+ networkd-ipv4ll.h
networkd-ipv6-proxy-ndp.c
networkd-ipv6-proxy-ndp.h
networkd-link-bus.c
networkd-radv.c
networkd-radv.h
networkd-network-bus.c
+ networkd-network-bus.h
networkd-network.c
networkd-network.h
networkd-route.c
_cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
_cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
- _cleanup_free_ void *p;
+ _cleanup_(erase_and_freep) void *p = NULL;
MACsec *s = userdata;
SecurityAssociation *dest;
size_t l;
r = unhexmem_full(rvalue, strlen(rvalue), true, &p, &l);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse key. Ignoring assignment: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse key. Ignoring assignment: %m");
return 0;
}
+
if (l != 16) {
/* See DEFAULT_SAK_LEN in drivers/net/macsec.c */
- explicit_bzero_safe(p, l);
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Invalid key length (%zu). Ignoring assignment", l);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid key length (%zu). Ignoring assignment", l);
return 0;
}
+ explicit_bzero_safe(dest->key, dest->key_len);
free_and_replace(dest->key, p);
dest->key_len = l;
}
static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
- _cleanup_free_ uint8_t *key = NULL;
+ _cleanup_(erase_and_freep) uint8_t *key = NULL;
size_t key_len;
int r;
return log_netdev_error_errno(netdev, r,
"Failed to read key from '%s', ignoring: %m",
sa->key_file);
- if (key_len != 16) {
- explicit_bzero_safe(key, key_len);
+
+ if (key_len != 16)
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
- "Invalid key length (%zu bytes), ignoring: %m",
- key_len);
- }
+ "Invalid key length (%zu bytes), ignoring: %m", key_len);
explicit_bzero_safe(sa->key, sa->key_len);
free_and_replace(sa->key, key);
#include "netdev/wireguard.h"
#include "netdev/fou-tunnel.h"
#include "netdev/l2tp-tunnel.h"
+#include "netdev/xfrm.h"
#include "vlan-util.h"
%}
struct ConfigPerfItem;
WireGuardPeer.PresharedKey, config_parse_wireguard_preshared_key, 0, 0
WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0
WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0
+Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id)
+Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent)
#include "netdev/vxcan.h"
#include "netdev/vxlan.h"
#include "netdev/wireguard.h"
+#include "netdev/xfrm.h"
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-link.h"
[NETDEV_KIND_L2TP] = &l2tptnl_vtable,
[NETDEV_KIND_MACSEC] = &macsec_vtable,
[NETDEV_KIND_NLMON] = &nlmon_vtable,
+ [NETDEV_KIND_XFRM] = &xfrm_vtable,
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_L2TP] = "l2tp",
[NETDEV_KIND_MACSEC] = "macsec",
[NETDEV_KIND_NLMON] = "nlmon",
+ [NETDEV_KIND_XFRM] = "xfrm",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
case NETDEV_KIND_ERSPAN:
independent = ERSPAN(netdev)->independent;
break;
+ case NETDEV_KIND_XFRM:
+ independent = XFRM(netdev)->independent;
+ break;
default:
break;
}
NETDEV_KIND_L2TP,
NETDEV_KIND_MACSEC,
NETDEV_KIND_NLMON,
+ NETDEV_KIND_XFRM,
_NETDEV_KIND_MAX,
_NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
_NETDEV_KIND_INVALID = -1
unsigned line,
const char *lvalue) {
- _cleanup_free_ void *key = NULL;
+ _cleanup_(erase_and_freep) void *key = NULL;
size_t len;
int r;
if (r < 0)
return log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue);
- if (len != WG_KEY_LEN) {
- explicit_bzero_safe(key, len);
+ if (len != WG_KEY_LEN)
return log_syntax(unit, LOG_ERR, filename, line, 0,
"Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.",
lvalue, len);
- }
memcpy(ret, key, WG_KEY_LEN);
return 0;
}
static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_KEY_LEN]) {
- _cleanup_free_ char *key = NULL;
+ _cleanup_(erase_and_freep) char *key = NULL;
size_t key_len;
int r;
if (r < 0)
return r;
- if (key_len != WG_KEY_LEN) {
- r = -EINVAL;
- goto finalize;
- }
+ if (key_len != WG_KEY_LEN)
+ return -EINVAL;
memcpy(dest, key, WG_KEY_LEN);
- r = 0;
-
-finalize:
- explicit_bzero_safe(key, key_len);
- return r;
+ return 0;
}
static int wireguard_peer_verify(WireguardPeer *peer) {
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "missing_network.h"
+#include "netdev/xfrm.h"
+
+static int xfrm_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *message) {
+ int if_idx, r;
+ Xfrm *x;
+
+ assert(netdev);
+ assert(message);
+
+ x = XFRM(netdev);
+
+ if (x->independent)
+ if_idx = LOOPBACK_IFINDEX;
+ else {
+ assert(link);
+ if (link->ifindex == 0)
+ return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ENODEV), "Could not get interface index: %m");
+ if_idx = link->ifindex;
+ }
+
+ r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, if_idx);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_LINK: %m");
+
+ r = sd_netlink_message_append_u32(message, IFLA_XFRM_IF_ID, x->if_id);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_IF_ID: %m");
+
+ return 0;
+}
+
+const NetDevVTable xfrm_vtable = {
+ .object_size = sizeof(Xfrm),
+ .sections = "Match\0NetDev\0Xfrm\0",
+ .fill_message_create = xfrm_fill_message_create,
+ .create_type = NETDEV_CREATE_STACKED
+};
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "netdev/netdev.h"
+
+typedef struct Xfrm {
+ NetDev meta;
+
+ uint32_t if_id;
+ bool independent;
+} Xfrm;
+
+DEFINE_NETDEV_CAST(XFRM, Xfrm);
+extern const NetDevVTable xfrm_vtable;
static bool is_bit_set(unsigned bit, uint32_t scope) {
assert(bit < sizeof(scope)*8);
- return scope & (1 << bit);
+ return scope & (UINT32_C(1) << bit);
}
static void set_bit(unsigned nr, uint32_t *addr) {
if (nr < BRIDGE_VLAN_BITMAP_MAX)
- addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
+ addr[nr / 32] |= (UINT32_C(1) << (nr % 32));
}
static int find_next_bit(int i, uint32_t x) {
static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) {
struct bridge_vlan_info br_vlan;
- int i, j, k, r, done, cnt;
+ int i, j, k, r, cnt;
uint16_t begin, end;
- bool untagged = false;
+ bool done, untagged = false;
assert(link);
assert(req);
assert(br_vid_bitmap);
assert(br_untagged_bitmap);
- i = cnt = -1;
+ cnt = 0;
begin = end = UINT16_MAX;
for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) {
base_bit = k * 32;
i = -1;
- done = 0;
+ done = false;
do {
j = find_next_bit(i, vid_map);
if (j > 0) {
goto next;
}
} else
- done = 1;
+ done = true;
if (begin != UINT16_MAX) {
cnt++;
i = j;
} while (!done);
}
- if (!cnt)
- return -EINVAL;
+ assert(cnt > 0);
return cnt;
}
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
- int r;
- uint16_t flags;
sd_netlink *rtnl;
+ uint16_t flags;
+ int r;
assert(link);
assert(link->manager);
return 0;
}
-static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) {
- int r;
- char *p;
- char *_rvalue = NULL;
- uint16_t _vid = UINT16_MAX;
- uint16_t _vid_end = UINT16_MAX;
-
- assert(rvalue);
- assert(vid);
- assert(vid_end);
-
- _rvalue = strdupa(rvalue);
- p = strchr(_rvalue, '-');
- if (p) {
- *p = '\0';
- p++;
- r = parse_vlanid(_rvalue, &_vid);
- if (r < 0)
- return r;
-
- if (_vid == 0)
- return -ERANGE;
-
- r = parse_vlanid(p, &_vid_end);
- if (r < 0)
- return r;
-
- if (_vid_end == 0)
- return -ERANGE;
- } else {
- r = parse_vlanid(_rvalue, &_vid);
- if (r < 0)
- return r;
-
- if (_vid == 0)
- return -ERANGE;
- }
-
- *vid = _vid;
- *vid_end = _vid_end;
- return r;
-}
-
int config_parse_brvlan_pvid(const char *unit, const char *filename,
unsigned line, const char *section,
unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data,
void *userdata) {
Network *network = userdata;
- int r;
uint16_t pvid;
+ int r;
+
r = parse_vlanid(rvalue, &pvid);
if (r < 0)
return r;
int ltype, const char *rvalue, void *data,
void *userdata) {
Network *network = userdata;
- int r;
uint16_t vid, vid_end;
+ int r;
assert(filename);
assert(section);
return 0;
}
- if (UINT16_MAX == vid_end)
- set_bit(vid++, network->br_vid_bitmap);
- else {
- if (vid >= vid_end) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
- return 0;
- }
- for (; vid <= vid_end; vid++)
- set_bit(vid, network->br_vid_bitmap);
- }
+ for (; vid <= vid_end; vid++)
+ set_bit(vid, network->br_vid_bitmap);
+
network->use_br_vlan = true;
return 0;
}
return 0;
}
- if (UINT16_MAX == vid_end) {
+ for (; vid <= vid_end; vid++) {
set_bit(vid, network->br_vid_bitmap);
set_bit(vid, network->br_untagged_bitmap);
- } else {
- if (vid >= vid_end) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
- return 0;
- }
- for (; vid <= vid_end; vid++) {
- set_bit(vid, network->br_vid_bitmap);
- set_bit(vid, network->br_untagged_bitmap);
- }
}
+
network->use_br_vlan = true;
return 0;
}
#include "conf-parser.h"
+#define BRIDGE_VLAN_BITMAP_MAX 4096
+#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
+
typedef struct Link Link;
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "networkd-dhcp-common.h"
+#include "networkd-network.h"
+#include "parse-util.h"
+#include "string-table.h"
+
+int config_parse_dhcp(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ AddressFamilyBoolean *dhcp = data, s;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ /* Note that this is mostly like
+ * config_parse_address_family_boolean(), except that it
+ * understands some old names for the enum values */
+
+ s = address_family_boolean_from_string(rvalue);
+ if (s < 0) {
+
+ /* Previously, we had a slightly different enum here,
+ * support its values for compatibility. */
+
+ if (streq(rvalue, "none"))
+ s = ADDRESS_FAMILY_NO;
+ else if (streq(rvalue, "v4"))
+ s = ADDRESS_FAMILY_IPV4;
+ else if (streq(rvalue, "v6"))
+ s = ADDRESS_FAMILY_IPV6;
+ else if (streq(rvalue, "both"))
+ s = ADDRESS_FAMILY_YES;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Failed to parse DHCP option, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "DHCP=%s is deprecated, please use DHCP=%s instead.",
+ rvalue, address_family_boolean_to_string(s));
+ }
+
+ *dhcp = s;
+ return 0;
+}
+
+int config_parse_section_route_table(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = data;
+ uint32_t rt;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &rt);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ if (streq_ptr(section, "DHCP")) {
+ network->dhcp_route_table = rt;
+ network->dhcp_route_table_set = true;
+ } else { /* section is IPv6AcceptRA */
+ network->ipv6_accept_ra_route_table = rt;
+ network->ipv6_accept_ra_route_table_set = true;
+ }
+
+ return 0;
+}
+
+int config_parse_iaid(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = data;
+ uint32_t iaid;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(network);
+
+ r = safe_atou32(rvalue, &iaid);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Unable to read IAID, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ network->iaid = iaid;
+ network->iaid_set = true;
+
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
+ "Failed to parse DHCP use domains setting");
+
+static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
+ [DHCP_USE_DOMAINS_NO] = "no",
+ [DHCP_USE_DOMAINS_ROUTE] = "route",
+ [DHCP_USE_DOMAINS_YES] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+#include "dhcp-identifier.h"
+#include "time-util.h"
+
+#define DHCP_ROUTE_METRIC 1024
+
+typedef enum DHCPUseDomains {
+ DHCP_USE_DOMAINS_NO,
+ DHCP_USE_DOMAINS_YES,
+ DHCP_USE_DOMAINS_ROUTE,
+ _DHCP_USE_DOMAINS_MAX,
+ _DHCP_USE_DOMAINS_INVALID = -1,
+} DHCPUseDomains;
+
+typedef struct DUID {
+ /* Value of Type in [DHCP] section */
+ DUIDType type;
+
+ uint8_t raw_data_len;
+ uint8_t raw_data[MAX_DUID_LEN];
+ usec_t llt_time;
+} DUID;
+
+const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
+DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
+CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-dhcp-server.h"
+
+#include "networkd-dhcp-server.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "networkd-network.h"
+#include "strv.h"
+
+static Address* link_find_dhcp_server_address(Link *link) {
+ Address *address;
+
+ assert(link);
+ assert(link->network);
+
+ /* The first statically configured address if there is any */
+ LIST_FOREACH(addresses, address, link->network->static_addresses) {
+
+ if (address->family != AF_INET)
+ continue;
+
+ if (in_addr_is_null(address->family, &address->in_addr))
+ continue;
+
+ return address;
+ }
+
+ /* If that didn't work, find a suitable address we got from the pool */
+ LIST_FOREACH(addresses, address, link->pool_addresses) {
+ if (address->family != AF_INET)
+ continue;
+
+ return address;
+ }
+
+ return NULL;
+}
+
+static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ unsigned i;
+
+ log_debug("Copying DNS server information from %s", link->ifname);
+
+ if (!link->network)
+ return 0;
+
+ for (i = 0; i < link->network->n_dns; i++) {
+ struct in_addr ia;
+
+ /* Only look for IPv4 addresses */
+ if (link->network->dns[i].family != AF_INET)
+ continue;
+
+ ia = link->network->dns[i].address.in;
+
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia;
+ }
+
+ if (link->network->dhcp_use_dns && link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int j, n;
+
+ n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_dns(s, addresses, n_addresses);
+}
+
+static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
+ _cleanup_free_ struct in_addr *addresses = NULL;
+ size_t n_addresses = 0, n_allocated = 0;
+ char **a;
+
+ if (!link->network)
+ return 0;
+
+ log_debug("Copying NTP server information from %s", link->ifname);
+
+ STRV_FOREACH(a, link->network->ntp) {
+ union in_addr_union ia;
+
+ /* Only look for IPv4 addresses */
+ if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
+ continue;
+
+ /* Never propagate obviously borked data */
+ if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
+ continue;
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
+ return log_oom();
+
+ addresses[n_addresses++] = ia.in;
+ }
+
+ if (link->network->dhcp_use_ntp && link->dhcp_lease) {
+ const struct in_addr *da = NULL;
+ int j, n;
+
+ n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
+ if (n > 0) {
+
+ if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
+ return log_oom();
+
+ for (j = 0; j < n; j++)
+ if (in4_addr_is_non_local(&da[j]))
+ addresses[n_addresses++] = da[j];
+ }
+ }
+
+ if (n_addresses <= 0)
+ return 0;
+
+ return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
+}
+
+int dhcp4_server_configure(Link *link) {
+ Address *address;
+ Link *uplink = NULL;
+ bool acquired_uplink = false;
+ int r;
+
+ address = link_find_dhcp_server_address(link);
+ if (!address)
+ return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBUSY),
+ "Failed to find suitable address for DHCPv4 server instance.");
+
+ /* use the server address' subnet as the pool */
+ r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
+ link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
+ if (r < 0)
+ return r;
+
+ /* TODO:
+ r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in);
+ if (r < 0)
+ return r;
+ */
+
+ if (link->network->dhcp_server_max_lease_time_usec > 0) {
+ r = sd_dhcp_server_set_max_lease_time(link->dhcp_server,
+ DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
+ if (r < 0)
+ return r;
+ }
+
+ if (link->network->dhcp_server_default_lease_time_usec > 0) {
+ r = sd_dhcp_server_set_default_lease_time(link->dhcp_server,
+ DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
+ if (r < 0)
+ return r;
+ }
+
+ if (link->network->dhcp_server_emit_dns) {
+ if (link->network->n_dhcp_server_dns > 0)
+ r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
+ else {
+ uplink = manager_find_uplink(link->manager, link);
+ acquired_uplink = true;
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
+ }
+
+ if (link->network->dhcp_server_emit_ntp) {
+ if (link->network->n_dhcp_server_ntp > 0)
+ r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
+ else {
+ if (!acquired_uplink)
+ uplink = manager_find_uplink(link->manager, link);
+
+ if (!uplink) {
+ log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
+ r = 0;
+ } else
+ r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
+
+ }
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
+ }
+
+ r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
+
+ if (link->network->dhcp_server_emit_timezone) {
+ _cleanup_free_ char *buffer = NULL;
+ const char *tz;
+
+ if (link->network->dhcp_server_timezone)
+ tz = link->network->dhcp_server_timezone;
+ else {
+ r = get_timezone(&buffer);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to determine timezone: %m");
+
+ tz = buffer;
+ }
+
+ r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
+ if (r < 0)
+ return r;
+ }
+ if (!sd_dhcp_server_is_running(link->dhcp_server)) {
+ r = sd_dhcp_server_start(link->dhcp_server);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
+ }
+
+ return 0;
+}
+
+int config_parse_dhcp_server_dns(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+ struct in_addr *m;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ break;
+
+ r = in_addr_from_string(AF_INET, w, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
+ continue;
+ }
+
+ m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
+
+ m[n->n_dhcp_server_dns++] = a.in;
+ n->dhcp_server_dns = m;
+ }
+
+ return 0;
+}
+
+int config_parse_dhcp_server_ntp(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+ struct in_addr *m;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = in_addr_from_string(AF_INET, w, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse NTP server address '%s', ignoring: %m", w);
+ continue;
+ }
+
+ m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
+
+ m[n->n_dhcp_server_ntp++] = a.in;
+ n->dhcp_server_ntp = m;
+ }
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+int dhcp4_server_configure(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
#include "hostname-util.h"
#include "parse-util.h"
#include "network-internal.h"
+#include "networkd-dhcp4.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-network.h"
+#include "string-table.h"
#include "string-util.h"
#include "sysctl-util.h"
route->priority = link->network->dhcp_route_metric;
route->table = table;
route->scope = route_scope_from_address(route, &address);
+ if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
+ route->prefsrc.in = address;
r = route_configure(route, link, dhcp4_route_handler);
if (r < 0)
route->priority = link->network->dhcp_route_metric;
route->table = table;
route->scope = route_scope_from_address(route, address);
+ if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
+ route->prefsrc.in = *address;
if (route_present_in_routes(route, new_routes, m))
continue;
return dhcp4_set_client_identifier(link);
}
+
+int config_parse_dhcp_max_attempts(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = data;
+ uint64_t a;
+ int r;
+
+ assert(network);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ network->dhcp_max_attempts = 0;
+ return 0;
+ }
+
+ if (streq(rvalue, "infinity")) {
+ network->dhcp_max_attempts = (uint64_t) -1;
+ return 0;
+ }
+
+ r = safe_atou64(rvalue, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (a == 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ network->dhcp_max_attempts = a;
+
+ return 0;
+}
+
+int config_parse_dhcp_black_listed_ip_address(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = data;
+ const char *p;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
+ return 0;
+ }
+
+ for (p = rvalue;;) {
+ _cleanup_free_ char *n = NULL;
+ union in_addr_union ip;
+
+ r = extract_first_word(&p, &n, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
+ rvalue);
+ return 0;
+ }
+ if (r == 0)
+ return 0;
+
+ r = in_addr_from_string(AF_INET, n, &ip);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
+ continue;
+ }
+
+ r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
+ if (r < 0)
+ return log_oom();
+
+ r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+ if (r < 0)
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
+ }
+
+ return 0;
+}
+
+int config_parse_dhcp_user_class(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***l = data;
+ int r;
+
+ assert(l);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *l = strv_free(*l);
+ return 0;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+
+ r = extract_first_word(&rvalue, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to split user classes option, ignoring: %s", rvalue);
+ break;
+ }
+ if (r == 0)
+ break;
+
+ if (strlen(w) > 255) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s length is not in the range 1-255, ignoring.", w);
+ continue;
+ }
+
+ r = strv_push(l, w);
+ if (r < 0)
+ return log_oom();
+
+ w = NULL;
+ }
+
+ return 0;
+}
+
+static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
+ [DHCP_CLIENT_ID_MAC] = "mac",
+ [DHCP_CLIENT_ID_DUID] = "duid",
+ [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
+ "Failed to parse client identifier type");
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+typedef enum DHCPClientIdentifier {
+ DHCP_CLIENT_ID_MAC,
+ DHCP_CLIENT_ID_DUID,
+ /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
+ * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
+ * requires the client id to be set to a custom string, reported at
+ * https://github.com/systemd/systemd/issues/7828 */
+ DHCP_CLIENT_ID_DUID_ONLY,
+ _DHCP_CLIENT_ID_MAX,
+ _DHCP_CLIENT_ID_INVALID = -1,
+} DHCPClientIdentifier;
+
+void dhcp4_release_old_lease(Link *link);
+int dhcp4_configure(Link *link);
+int dhcp4_set_client_identifier(Link *link);
+int dhcp4_set_promote_secondaries(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
#include "hostname-util.h"
#include "missing_network.h"
#include "network-internal.h"
+#include "networkd-dhcp6.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "siphash24.h"
#include "radv-internal.h"
static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
+static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
+static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
+static int dhcp6_prefix_remove_all(Manager *m, Link *link);
static bool dhcp6_get_prefix_delegation(Link *link) {
if (!link->network)
if (r < 0 && r != -EEXIST)
return r;
- r = manager_dhcp6_prefix_add(link->manager, prefix, link);
+ r = dhcp6_prefix_add(link->manager, prefix, link);
if (r < 0)
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0)
- log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnetl: %m");
+ log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnet: %m");
return 1;
}
if (!dhcp6_get_prefix_delegation(link))
continue;
- assigned_link = manager_dhcp6_prefix_get(manager, &prefix.in6);
+ assigned_link = dhcp6_prefix_get(manager, &prefix.in6);
if (assigned_link && assigned_link != link)
continue;
log_link_warning(link, "DHCPv6 lease lost");
(void) dhcp6_lease_pd_prefix_lost(client, link);
- (void) manager_dhcp6_prefix_remove_all(link->manager, link);
+ (void) dhcp6_prefix_remove_all(link->manager, link);
link->dhcp6_configured = false;
break;
return 0;
}
+
+static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
+ assert_return(m, NULL);
+ assert_return(addr, NULL);
+
+ return hashmap_get(m->dhcp6_prefixes, addr);
+}
+
+static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST)
+ log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
+
+ return 0;
+}
+
+static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
+ _cleanup_free_ struct in6_addr *a = NULL;
+ _cleanup_free_ char *buf = NULL;
+ Link *assigned_link;
+ Route *route;
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
+ 0, 0, 0, &route);
+ if (r < 0)
+ return r;
+
+ r = route_configure(route, link, dhcp6_route_add_handler);
+ if (r < 0)
+ return r;
+
+ (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
+ log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
+
+ assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
+ if (assigned_link) {
+ assert(assigned_link == link);
+ return 0;
+ }
+
+ a = newdup(struct in6_addr, addr, 1);
+ if (!a)
+ return -ENOMEM;
+
+ r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = hashmap_put(m->dhcp6_prefixes, a, link);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(a);
+ link_ref(link);
+ return 0;
+}
+
+static int dhcp6_prefix_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
+ int r;
+
+ assert(link);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0)
+ log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
+
+ return 1;
+}
+
+int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
+ _cleanup_free_ struct in6_addr *a = NULL;
+ _cleanup_(link_unrefp) Link *l = NULL;
+ _cleanup_free_ char *buf = NULL;
+ Route *route;
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
+ if (!l)
+ return -EINVAL;
+
+ (void) sd_radv_remove_prefix(l->radv, addr, 64);
+ r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
+ if (r < 0)
+ return r;
+
+ r = route_remove(route, l, dhcp6_prefix_remove_handler);
+ if (r < 0)
+ return r;
+
+ (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
+ log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
+
+ return 0;
+}
+
+static int dhcp6_prefix_remove_all(Manager *m, Link *link) {
+ struct in6_addr *addr;
+ Iterator i;
+ Link *l;
+
+ assert_return(m, -EINVAL);
+ assert_return(link, -EINVAL);
+
+ HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
+ if (l == link)
+ (void) dhcp6_prefix_remove(m, addr);
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-dhcp6-client.h"
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+typedef struct Manager Manager;
+
+int dhcp6_request_prefix_delegation(Link *link);
+int dhcp6_configure(Link *link);
+int dhcp6_request_address(Link *link, int ir);
+int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
+int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
#include "network-internal.h"
#include "networkd-address.h"
-#include "networkd-manager.h"
+#include "networkd-ipv4ll.h"
#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "parse-util.h"
static int ipv4ll_address_lost(Link *link) {
_cleanup_(address_freep) Address *address = NULL;
return 0;
}
+
+int config_parse_ipv4ll(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ AddressFamilyBoolean *link_local = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ /* Note that this is mostly like
+ * config_parse_address_family_boolean(), except that it
+ * applies only to IPv4 */
+
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to parse %s=%s, ignoring assignment. "
+ "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
+ lvalue, rvalue, lvalue);
+ return 0;
+ }
+
+ SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
+
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
+ lvalue, rvalue, address_family_boolean_to_string(*link_local));
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "conf-parser.h"
+
+#define IPV4LL_ROUTE_METRIC 2048
+
+typedef struct Link Link;
+
+int ipv4ll_configure(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
#include "netlink-util.h"
#include "network-internal.h"
#include "networkd-can.h"
+#include "networkd-dhcp-server.h"
+#include "networkd-dhcp4.h"
+#include "networkd-dhcp6.h"
+#include "networkd-ipv4ll.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-link-bus.h"
#include "networkd-link.h"
_cleanup_free_ char *value = NULL;
int r;
- r = sysctl_read_ip_property(AF_INET6, link->ifname, "disable_ipv6", &value);
+ assert(link);
+ assert(link->ifname);
+
+ if (link->sysctl_ipv6_enabled >= 0)
+ return link->sysctl_ipv6_enabled;
+
+ const char *ifname = link->ifname; /* work around bogus gcc warning */
+ r = sysctl_read_ip_property(AF_INET6, ifname, "disable_ipv6", &value);
if (r < 0)
return log_link_warning_errno(link, r,
"Failed to read net.ipv6.conf.%s.disable_ipv6 sysctl property: %m",
- link->ifname);
+ ifname);
link->sysctl_ipv6_enabled = value[0] == '0';
return link->sysctl_ipv6_enabled;
if (!link->network)
return false;
- if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon"))
+ if (STRPTR_IN_SET(link->kind,
+ "vrf", "wireguard", "ipip", "gre", "ip6gre","ip6tnl", "sit", "vti",
+ "vti6", "can", "vcan", "vxcan", "nlmon", "xfrm"))
return false;
/* L3 or L3S mode do not support ARP. */
if (link->network->bond)
return false;
- if (link->network->bond)
- return false;
-
return link->network->link_local & mask;
}
link_dirty(link);
}
-static Address* link_find_dhcp_server_address(Link *link) {
- Address *address;
-
- assert(link);
- assert(link->network);
-
- /* The first statically configured address if there is any */
- LIST_FOREACH(addresses, address, link->network->static_addresses) {
-
- if (address->family != AF_INET)
- continue;
-
- if (in_addr_is_null(address->family, &address->in_addr))
- continue;
-
- return address;
- }
-
- /* If that didn't work, find a suitable address we got from the pool */
- LIST_FOREACH(addresses, address, link->pool_addresses) {
- if (address->family != AF_INET)
- continue;
-
- return address;
- }
-
- return NULL;
-}
-
static int link_join_netdevs_after_configured(Link *link) {
NetDev *netdev;
Iterator i;
return 1;
}
-static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
- _cleanup_free_ struct in_addr *addresses = NULL;
- size_t n_addresses = 0, n_allocated = 0;
- unsigned i;
-
- log_debug("Copying DNS server information from %s", link->ifname);
-
- if (!link->network)
- return 0;
-
- for (i = 0; i < link->network->n_dns; i++) {
- struct in_addr ia;
-
- /* Only look for IPv4 addresses */
- if (link->network->dns[i].family != AF_INET)
- continue;
-
- ia = link->network->dns[i].address.in;
-
- /* Never propagate obviously borked data */
- if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
- continue;
-
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
- return log_oom();
-
- addresses[n_addresses++] = ia;
- }
-
- if (link->network->dhcp_use_dns && link->dhcp_lease) {
- const struct in_addr *da = NULL;
- int j, n;
-
- n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
- if (n > 0) {
-
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
- return log_oom();
-
- for (j = 0; j < n; j++)
- if (in4_addr_is_non_local(&da[j]))
- addresses[n_addresses++] = da[j];
- }
- }
-
- if (n_addresses <= 0)
- return 0;
-
- return sd_dhcp_server_set_dns(s, addresses, n_addresses);
-}
-
-static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
- _cleanup_free_ struct in_addr *addresses = NULL;
- size_t n_addresses = 0, n_allocated = 0;
- char **a;
-
- if (!link->network)
- return 0;
-
- log_debug("Copying NTP server information from %s", link->ifname);
-
- STRV_FOREACH(a, link->network->ntp) {
- union in_addr_union ia;
-
- /* Only look for IPv4 addresses */
- if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
- continue;
-
- /* Never propagate obviously borked data */
- if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
- continue;
-
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
- return log_oom();
-
- addresses[n_addresses++] = ia.in;
- }
-
- if (link->network->dhcp_use_ntp && link->dhcp_lease) {
- const struct in_addr *da = NULL;
- int j, n;
-
- n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
- if (n > 0) {
-
- if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
- return log_oom();
-
- for (j = 0; j < n; j++)
- if (in4_addr_is_non_local(&da[j]))
- addresses[n_addresses++] = da[j];
- }
- }
-
- if (n_addresses <= 0)
- return 0;
-
- return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
-}
-
static int link_set_bridge_fdb(Link *link) {
FdbEntry *fdb_entry;
int r;
/* now that we can figure out a default address for the dhcp server,
start it */
if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) {
- Address *address;
- Link *uplink = NULL;
- bool acquired_uplink = false;
-
- address = link_find_dhcp_server_address(link);
- if (!address) {
- log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
+ r = dhcp4_server_configure(link);
+ if (r < 0) {
link_enter_failed(link);
- return 0;
- }
-
- /* use the server address' subnet as the pool */
- r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
- link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
- if (r < 0)
return r;
-
- /* TODO:
- r = sd_dhcp_server_set_router(link->dhcp_server,
- &main_address->in_addr.in);
- if (r < 0)
- return r;
- */
-
- if (link->network->dhcp_server_max_lease_time_usec > 0) {
- r = sd_dhcp_server_set_max_lease_time(
- link->dhcp_server,
- DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
- if (r < 0)
- return r;
- }
-
- if (link->network->dhcp_server_default_lease_time_usec > 0) {
- r = sd_dhcp_server_set_default_lease_time(
- link->dhcp_server,
- DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
- if (r < 0)
- return r;
- }
-
- if (link->network->dhcp_server_emit_dns) {
-
- if (link->network->n_dhcp_server_dns > 0)
- r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
- else {
- uplink = manager_find_uplink(link->manager, link);
- acquired_uplink = true;
-
- if (!uplink) {
- log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
- r = 0;
- } else
- r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
- }
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
- }
-
- if (link->network->dhcp_server_emit_ntp) {
-
- if (link->network->n_dhcp_server_ntp > 0)
- r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
- else {
- if (!acquired_uplink)
- uplink = manager_find_uplink(link->manager, link);
-
- if (!uplink) {
- log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
- r = 0;
- } else
- r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
-
- }
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
- }
-
- r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
- if (r < 0)
- return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
-
- if (link->network->dhcp_server_emit_timezone) {
- _cleanup_free_ char *buffer = NULL;
- const char *tz = NULL;
-
- if (link->network->dhcp_server_timezone)
- tz = link->network->dhcp_server_timezone;
- else {
- r = get_timezone(&buffer);
- if (r < 0)
- log_warning_errno(r, "Failed to determine timezone: %m");
- else
- tz = buffer;
- }
-
- if (tz) {
- r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
- if (r < 0)
- return r;
- }
}
- if (!sd_dhcp_server_is_running(link->dhcp_server)) {
- r = sd_dhcp_server_start(link->dhcp_server);
- if (r < 0) {
- log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
-
- link_enter_failed(link);
-
- return 0;
- }
- }
-
log_link_debug(link, "Offering DHCPv4 leases");
}
int link_set_mtu(Link *link, uint32_t mtu);
-int ipv4ll_configure(Link *link);
bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask);
-void dhcp4_release_old_lease(Link *link);
-int dhcp4_configure(Link *link);
-int dhcp4_set_client_identifier(Link *link);
-int dhcp4_set_promote_secondaries(Link *link);
-int dhcp6_request_prefix_delegation(Link *link);
-int dhcp6_configure(Link *link);
-int dhcp6_request_address(Link *link, int ir);
-int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link);
-
int link_stop_clients(Link *link, bool may_keep_dhcp);
const char* link_state_to_string(LinkState s) _const_;
#include "local-addresses.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "networkd-dhcp6.h"
#include "networkd-link-bus.h"
#include "networkd-manager.h"
+#include "networkd-network-bus.h"
#include "networkd-speed-meter.h"
#include "ordered-set.h"
#include "path-util.h"
return 1;
}
-Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
- assert_return(m, NULL);
- assert_return(addr, NULL);
-
- return hashmap_get(m->dhcp6_prefixes, addr);
-}
-
-static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(link);
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST)
- log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
-
- return 0;
-}
-
-int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
- _cleanup_free_ struct in6_addr *a = NULL;
- _cleanup_free_ char *buf = NULL;
- Link *assigned_link;
- Route *route;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(addr, -EINVAL);
-
- r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
- 0, 0, 0, &route);
- if (r < 0)
- return r;
-
- r = route_configure(route, link, dhcp6_route_add_handler);
- if (r < 0)
- return r;
-
- (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
- log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
-
- assigned_link = hashmap_get(m->dhcp6_prefixes, addr);
- if (assigned_link) {
- assert(assigned_link == link);
- return 0;
- }
-
- a = newdup(struct in6_addr, addr, 1);
- if (!a)
- return -ENOMEM;
-
- r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_put(m->dhcp6_prefixes, a, link);
- if (r < 0)
- return r;
-
- TAKE_PTR(a);
- link_ref(link);
- return 0;
-}
-
-static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
- int r;
-
- assert(link);
-
- r = sd_netlink_message_get_errno(m);
- if (r < 0)
- log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
-
- return 1;
-}
-
-static int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
- _cleanup_free_ struct in6_addr *a = NULL;
- _cleanup_(link_unrefp) Link *l = NULL;
- _cleanup_free_ char *buf = NULL;
- Route *route;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(addr, -EINVAL);
-
- l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a);
- if (!l)
- return -EINVAL;
-
- (void) sd_radv_remove_prefix(l->radv, addr, 64);
- r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, 0, 0, 0, &route);
- if (r < 0)
- return r;
-
- r = route_remove(route, l, dhcp6_route_remove_handler);
- if (r < 0)
- return r;
-
- (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
- log_link_debug(l, "Removing prefix route %s/64", strnull(buf));
-
- return 0;
-}
-
-int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) {
- struct in6_addr *addr;
- Iterator i;
- Link *l;
-
- assert_return(m, -EINVAL);
- assert_return(link, -EINVAL);
-
- HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i)
- if (l == link)
- (void) manager_dhcp6_prefix_remove(m, addr);
-
- return 0;
-}
-
int manager_new(Manager **ret) {
_cleanup_(manager_freep) Manager *m = NULL;
int r;
free(m->state_file);
while ((a = hashmap_first_key(m->dhcp6_prefixes)))
- (void) manager_dhcp6_prefix_remove(m, a);
+ (void) dhcp6_prefix_remove(m, a);
hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_steal_first(m->links))) {
int manager_set_timezone(Manager *m, const char *timezone);
int manager_request_product_uuid(Manager *m, Link *link);
-Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
-int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
-int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
-
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
#include "sd-ndisc.h"
#include "missing_network.h"
+#include "networkd-dhcp6.h"
#include "networkd-ndisc.h"
#include "networkd-route.h"
#include "strv.h"
continue;
}
+ if (set_contains(network->ndisc_black_listed_prefix, &ip.in6))
+ continue;
+
r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
if (r < 0)
return log_oom();
r = set_put(network->ndisc_black_listed_prefix, a);
if (r < 0) {
- if (r == -EEXIST)
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
- else
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
continue;
}
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "networkd-manager.h"
+#include "networkd-network-bus.h"
#include "string-util.h"
#include "strv.h"
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+typedef struct Link Link;
+
+extern const sd_bus_vtable network_vtable[];
+
+int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
#include "conf-parser.h"
#include "network-internal.h"
#include "networkd-conf.h"
+#include "networkd-dhcp-common.h"
+#include "networkd-dhcp-server.h"
+#include "networkd-dhcp4.h"
+#include "networkd-ipv4ll.h"
#include "networkd-ndisc.h"
#include "networkd-network.h"
#include "vlan-util.h"
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac)
-Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
-Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name)
+Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path)
+Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver)
+Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type)
+Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
+Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
Network.L2TP, config_parse_stacked_netdev, NETDEV_KIND_L2TP, offsetof(Network, stacked_netdev_names)
Network.MACsec, config_parse_stacked_netdev, NETDEV_KIND_MACSEC, offsetof(Network, stacked_netdev_names)
Network.Tunnel, config_parse_stacked_netdev, _NETDEV_KIND_TUNNEL, offsetof(Network, stacked_netdev_names)
+Network.Xfrm, config_parse_stacked_netdev, NETDEV_KIND_XFRM, offsetof(Network, stacked_netdev_names)
Network.VRF, config_parse_ifname, 0, offsetof(Network, vrf_name)
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
- strv_isempty(network->match_name) && !network->conditions)
+ strv_isempty(network->match_name) && strv_isempty(network->match_property) &&
+ !network->conditions)
log_warning("%s: No valid settings found in the [Match] section. "
"The file will match all interfaces. "
"If that is intended, please add Name=* in the [Match] section.",
strv_free(network->match_driver);
strv_free(network->match_type);
strv_free(network->match_name);
+ strv_free(network->match_property);
condition_free_list(network->conditions);
free(network->description);
int network_get(Manager *manager, sd_device *device,
const char *ifname, const struct ether_addr *address,
Network **ret) {
- const char *path = NULL, *driver = NULL, *devtype = NULL;
Network *network;
Iterator i;
assert(manager);
assert(ret);
- if (device) {
- (void) sd_device_get_property_value(device, "ID_PATH", &path);
-
- (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
-
- (void) sd_device_get_devtype(device, &devtype);
- }
-
ORDERED_HASHMAP_FOREACH(network, manager->networks, i)
- if (net_match_config(network->match_mac, network->match_path,
- network->match_driver, network->match_type,
- network->match_name,
- address, path, driver, devtype, ifname)) {
+ if (net_match_config(network->match_mac, network->match_path, network->match_driver,
+ network->match_type, network->match_name, network->match_property,
+ device, address, ifname)) {
if (network->match_name && device) {
const char *attr;
uint8_t name_assign_type = NET_NAME_UNKNOWN;
assert(IN_SET(kind,
NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
- NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
+ NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
+ NETDEV_KIND_XFRM));
if (!ifname_valid(rvalue)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
return 0;
}
-int config_parse_ipv4ll(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- AddressFamilyBoolean *link_local = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Note that this is mostly like
- * config_parse_address_family_boolean(), except that it
- * applies only to IPv4 */
-
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse %s=%s, ignoring assignment. "
- "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.",
- lvalue, rvalue, lvalue);
- return 0;
- }
-
- SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r);
-
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.",
- lvalue, rvalue, address_family_boolean_to_string(*link_local));
-
- return 0;
-}
-
-int config_parse_dhcp(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- AddressFamilyBoolean *dhcp = data, s;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- /* Note that this is mostly like
- * config_parse_address_family_boolean(), except that it
- * understands some old names for the enum values */
-
- s = address_family_boolean_from_string(rvalue);
- if (s < 0) {
-
- /* Previously, we had a slightly different enum here,
- * support its values for compatibility. */
-
- if (streq(rvalue, "none"))
- s = ADDRESS_FAMILY_NO;
- else if (streq(rvalue, "v4"))
- s = ADDRESS_FAMILY_IPV4;
- else if (streq(rvalue, "v6"))
- s = ADDRESS_FAMILY_IPV6;
- else if (streq(rvalue, "both"))
- s = ADDRESS_FAMILY_YES;
- else {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Failed to parse DHCP option, ignoring: %s", rvalue);
- return 0;
- }
-
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "DHCP=%s is deprecated, please use DHCP=%s instead.",
- rvalue, address_family_boolean_to_string(s));
- }
-
- *dhcp = s;
- return 0;
-}
-
-static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
- [DHCP_CLIENT_ID_MAC] = "mac",
- [DHCP_CLIENT_ID_DUID] = "duid",
- [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
- "Failed to parse client identifier type");
-
int config_parse_ipv6token(
const char* unit,
const char *filename,
return free_and_replace(*datap, tz);
}
-int config_parse_dhcp_server_dns(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *n = data;
- const char *p = rvalue;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- for (;;) {
- _cleanup_free_ char *w = NULL;
- union in_addr_union a;
- struct in_addr *m;
-
- r = extract_first_word(&p, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to extract word, ignoring: %s", rvalue);
- return 0;
- }
- if (r == 0)
- break;
-
- r = in_addr_from_string(AF_INET, w, &a);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
- continue;
- }
-
- m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
- if (!m)
- return log_oom();
-
- m[n->n_dhcp_server_dns++] = a.in;
- n->dhcp_server_dns = m;
- }
-
- return 0;
-}
-
-int config_parse_radv_dns(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *n = data;
- const char *p = rvalue;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- for (;;) {
- _cleanup_free_ char *w = NULL;
- union in_addr_union a;
-
- r = extract_first_word(&p, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to extract word, ignoring: %s", rvalue);
- return 0;
- }
- if (r == 0)
- break;
-
- if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
- struct in6_addr *m;
-
- m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
- if (!m)
- return log_oom();
-
- m[n->n_router_dns++] = a.in6;
- n->router_dns = m;
-
- } else
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Failed to parse DNS server address, ignoring: %s", w);
- }
-
- return 0;
-}
-
-int config_parse_radv_search_domains(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *n = data;
- const char *p = rvalue;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- for (;;) {
- _cleanup_free_ char *w = NULL, *idna = NULL;
-
- r = extract_first_word(&p, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to extract word, ignoring: %s", rvalue);
- return 0;
- }
- if (r == 0)
- break;
-
- r = dns_name_apply_idna(w, &idna);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
- continue;
- } else if (r == 0)
- /* transfer ownership to simplify subsequent operations */
- idna = TAKE_PTR(w);
-
- r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
- if (r < 0)
- return r;
-
- r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int config_parse_dhcp_server_ntp(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *n = data;
- const char *p = rvalue;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- for (;;) {
- _cleanup_free_ char *w = NULL;
- union in_addr_union a;
- struct in_addr *m;
-
- r = extract_first_word(&p, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to extract word, ignoring: %s", rvalue);
- return 0;
- }
- if (r == 0)
- return 0;
-
- r = in_addr_from_string(AF_INET, w, &a);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse NTP server address '%s', ignoring: %m", w);
- continue;
- }
-
- m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
- if (!m)
- return log_oom();
-
- m[n->n_dhcp_server_ntp++] = a.in;
- n->dhcp_server_ntp = m;
- }
-}
-
int config_parse_dns(
const char *unit,
const char *filename,
return 0;
}
-int config_parse_dhcp_user_class(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- char ***l = data;
- int r;
-
- assert(l);
- assert(lvalue);
- assert(rvalue);
-
- if (isempty(rvalue)) {
- *l = strv_free(*l);
- return 0;
- }
-
- for (;;) {
- _cleanup_free_ char *w = NULL;
-
- r = extract_first_word(&rvalue, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to split user classes option, ignoring: %s", rvalue);
- break;
- }
- if (r == 0)
- break;
-
- if (strlen(w) > 255) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s length is not in the range 1-255, ignoring.", w);
- continue;
- }
-
- r = strv_push(l, w);
- if (r < 0)
- return log_oom();
-
- w = NULL;
- }
-
- return 0;
-}
-
-int config_parse_section_route_table(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *network = data;
- uint32_t rt;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = safe_atou32(rvalue, &rt);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
- return 0;
- }
-
- if (streq_ptr(section, "DHCP")) {
- network->dhcp_route_table = rt;
- network->dhcp_route_table_set = true;
- } else { /* section is IPv6AcceptRA */
- network->ipv6_accept_ra_route_table = rt;
- network->ipv6_accept_ra_route_table_set = true;
- }
-
- return 0;
-}
-
-int config_parse_dhcp_max_attempts(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *network = data;
- uint64_t a;
- int r;
-
- assert(network);
- assert(lvalue);
- assert(rvalue);
-
- if (isempty(rvalue)) {
- network->dhcp_max_attempts = 0;
- return 0;
- }
-
- if (streq(rvalue, "infinity")) {
- network->dhcp_max_attempts = (uint64_t) -1;
- return 0;
- }
-
- r = safe_atou64(rvalue, &a);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
- return 0;
- }
-
- if (a == 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
- return 0;
- }
-
- network->dhcp_max_attempts = a;
-
- return 0;
-}
-
-int config_parse_dhcp_black_listed_ip_address(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *network = data;
- const char *p;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
- return 0;
- }
-
- for (p = rvalue;;) {
- _cleanup_free_ char *n = NULL;
- union in_addr_union ip;
-
- r = extract_first_word(&p, &n, NULL, 0);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
- rvalue);
- return 0;
- }
- if (r == 0)
- return 0;
-
- r = in_addr_from_string(AF_INET, n, &ip);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
- continue;
- }
-
- r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
- }
-
- return 0;
-}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
- "Failed to parse DHCP use domains setting");
-
-static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
- [DHCP_USE_DOMAINS_NO] = "no",
- [DHCP_USE_DOMAINS_ROUTE] = "route",
- [DHCP_USE_DOMAINS_YES] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
-
-int config_parse_iaid(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Network *network = data;
- uint32_t iaid;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(network);
-
- r = safe_atou32(rvalue, &iaid);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Unable to read IAID, ignoring assignment: %s", rvalue);
- return 0;
- }
-
- network->iaid = iaid;
- network->iaid_set = true;
-
- return 0;
-}
-
int config_parse_required_for_online(
const char *unit,
const char *filename,
#include "condition.h"
#include "conf-parser.h"
-#include "dhcp-identifier.h"
#include "hashmap.h"
#include "netdev/bridge.h"
#include "netdev/netdev.h"
#include "networkd-address-label.h"
#include "networkd-address.h"
#include "networkd-brvlan.h"
+#include "networkd-dhcp-common.h"
+#include "networkd-dhcp4.h"
#include "networkd-fdb.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-lldp-rx.h"
#include "ordered-set.h"
#include "resolve-util.h"
-#define DHCP_ROUTE_METRIC 1024
-#define IPV4LL_ROUTE_METRIC 2048
-
-#define BRIDGE_VLAN_BITMAP_MAX 4096
-#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
-
-typedef enum DHCPClientIdentifier {
- DHCP_CLIENT_ID_MAC,
- DHCP_CLIENT_ID_DUID,
- /* The following option may not be good for RFC regarding DHCP (3315 and 4361).
- * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK
- * requires the client id to be set to a custom string, reported at
- * https://github.com/systemd/systemd/issues/7828 */
- DHCP_CLIENT_ID_DUID_ONLY,
- _DHCP_CLIENT_ID_MAX,
- _DHCP_CLIENT_ID_INVALID = -1,
-} DHCPClientIdentifier;
-
typedef enum IPv6PrivacyExtensions {
/* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
IPV6_PRIVACY_EXTENSIONS_NO,
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
} IPv6PrivacyExtensions;
-typedef enum DHCPUseDomains {
- DHCP_USE_DOMAINS_NO,
- DHCP_USE_DOMAINS_YES,
- DHCP_USE_DOMAINS_ROUTE,
- _DHCP_USE_DOMAINS_MAX,
- _DHCP_USE_DOMAINS_INVALID = -1,
-} DHCPUseDomains;
-
-typedef struct DUID {
- /* Value of Type in [DHCP] section */
- DUIDType type;
-
- uint8_t raw_data_len;
- uint8_t raw_data[MAX_DUID_LEN];
- usec_t llt_time;
-} DUID;
-
-typedef enum RADVPrefixDelegation {
- RADV_PREFIX_DELEGATION_NONE,
- RADV_PREFIX_DELEGATION_STATIC,
- RADV_PREFIX_DELEGATION_DHCP6,
- RADV_PREFIX_DELEGATION_BOTH,
- _RADV_PREFIX_DELEGATION_MAX,
- _RADV_PREFIX_DELEGATION_INVALID = -1,
-} RADVPrefixDelegation;
-
typedef enum KeepConfiguration {
KEEP_CONFIGURATION_NO = 0,
KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0,
char **match_driver;
char **match_type;
char **match_name;
+ char **match_property;
LIST_HEAD(Condition, conditions);
char *description;
NetDev *bridge;
NetDev *bond;
NetDev *vrf;
+ NetDev *xfrm;
Hashmap *stacked_netdevs;
char *bridge_name;
char *bond_name;
bool network_has_static_ipv6_addresses(Network *network);
CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev);
-CONFIG_PARSER_PROTOTYPE(config_parse_domains);
CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
-CONFIG_PARSER_PROTOTYPE(config_parse_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
+CONFIG_PARSER_PROTOTYPE(config_parse_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
-CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
-CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
-CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
-/* Legacy IPv4LL support */
-CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-extern const sd_bus_vtable network_vtable[];
-
-int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
-int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
-
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
-const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
-DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
-
-const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
-RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
-
const char* keep_configuration_to_string(KeepConfiguration i) _const_;
KeepConfiguration keep_configuration_from_string(const char *s) _pure_;
#include <netinet/icmp6.h>
#include <arpa/inet.h>
+#include "dns-domain.h"
#include "networkd-address.h"
#include "networkd-manager.h"
#include "networkd-radv.h"
#include "string-table.h"
#include "strv.h"
-static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
- [RADV_PREFIX_DELEGATION_NONE] = "no",
- [RADV_PREFIX_DELEGATION_STATIC] = "static",
- [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
- [RADV_PREFIX_DELEGATION_BOTH] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
- radv_prefix_delegation,
- RADVPrefixDelegation,
- RADV_PREFIX_DELEGATION_BOTH);
-
-int config_parse_router_prefix_delegation(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Network *network = userdata;
- RADVPrefixDelegation d;
-
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- d = radv_prefix_delegation_from_string(rvalue);
- if (d < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue);
- return 0;
- }
-
- network->router_prefix_delegation = d;
-
- return 0;
-}
-
-int config_parse_router_preference(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Network *network = userdata;
-
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (streq(rvalue, "high"))
- network->router_preference = SD_NDISC_PREFERENCE_HIGH;
- else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
- network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
- else if (streq(rvalue, "low"))
- network->router_preference = SD_NDISC_PREFERENCE_LOW;
- else
- log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue);
-
- return 0;
-}
-
void prefix_free(Prefix *prefix) {
if (!prefix)
return;
return radv_emit_dns(link);
}
+
+int config_parse_radv_dns(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ break;
+
+ if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
+ struct in6_addr *m;
+
+ m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
+ if (!m)
+ return log_oom();
+
+ m[n->n_router_dns++] = a.in6;
+ n->router_dns = m;
+
+ } else
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Failed to parse DNS server address, ignoring: %s", w);
+ }
+
+ return 0;
+}
+
+int config_parse_radv_search_domains(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL, *idna = NULL;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0)
+ break;
+
+ r = dns_name_apply_idna(w, &idna);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to apply IDNA to domain name '%s', ignoring: %m", w);
+ continue;
+ } else if (r == 0)
+ /* transfer ownership to simplify subsequent operations */
+ idna = TAKE_PTR(w);
+
+ r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = {
+ [RADV_PREFIX_DELEGATION_NONE] = "no",
+ [RADV_PREFIX_DELEGATION_STATIC] = "static",
+ [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6",
+ [RADV_PREFIX_DELEGATION_BOTH] = "yes",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(
+ radv_prefix_delegation,
+ RADVPrefixDelegation,
+ RADV_PREFIX_DELEGATION_BOTH);
+
+int config_parse_router_prefix_delegation(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = userdata;
+ RADVPrefixDelegation d;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ d = radv_prefix_delegation_from_string(rvalue);
+ if (d < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue);
+ return 0;
+ }
+
+ network->router_prefix_delegation = d;
+
+ return 0;
+}
+
+int config_parse_router_preference(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (streq(rvalue, "high"))
+ network->router_preference = SD_NDISC_PREFERENCE_HIGH;
+ else if (STR_IN_SET(rvalue, "medium", "normal", "default"))
+ network->router_preference = SD_NDISC_PREFERENCE_MEDIUM;
+ else if (streq(rvalue, "low"))
+ network->router_preference = SD_NDISC_PREFERENCE_LOW;
+ else
+ log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue);
+
+ return 0;
+}
typedef struct Prefix Prefix;
+typedef enum RADVPrefixDelegation {
+ RADV_PREFIX_DELEGATION_NONE,
+ RADV_PREFIX_DELEGATION_STATIC,
+ RADV_PREFIX_DELEGATION_DHCP6,
+ RADV_PREFIX_DELEGATION_BOTH,
+ _RADV_PREFIX_DELEGATION_MAX,
+ _RADV_PREFIX_DELEGATION_INVALID = -1,
+} RADVPrefixDelegation;
+
struct Prefix {
Network *network;
NetworkConfigSection *section;
DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free);
+int radv_emit_dns(Link *link);
+int radv_configure(Link *link);
+
+const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
+RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
+
CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
-
-int radv_emit_dns(Link *link);
-int radv_configure(Link *link);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
#include "in-addr-util.h"
#include "missing_network.h"
#include "netlink-util.h"
+#include "networkd-ipv4ll.h"
#include "networkd-manager.h"
#include "networkd-route.h"
#include "parse-util.h"
assert_se(network = new0(Network, 1));
network->n_ref = 1;
assert_se(network->filename = strdup("hogehoge.network"));
- assert_se(config_parse_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
+ assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
assert_se(network->n_static_addresses == 1);
assert_se(network_verify(network) >= 0);
test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0);
}
+static void test_config_parse_match_ifnames(void) {
+ _cleanup_strv_free_ char **names = NULL;
+
+ assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
+ assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0);
+ assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "aaa bbb ccc", &names, NULL) == 0);
+
+ strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc"));
+}
+
+static void test_config_parse_match_strv(void) {
+ _cleanup_strv_free_ char **names = NULL;
+
+ assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0);
+ assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0);
+ assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0,
+ "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"", &names, NULL) == 0);
+
+ strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "KEY=val", "KEY2=val with space", "KEY3=val with \"quotation\""));
+}
+
int main(int argc, char **argv) {
log_parse_environment();
log_open();
test_config_parse_duid_rawdata();
test_config_parse_hwaddr();
test_config_parse_address();
+ test_config_parse_match_ifnames();
+ test_config_parse_match_strv();
return 0;
}
int master_pty_socket,
FDSet *fds) {
- _cleanup_close_ int master = -1;
_cleanup_free_ char *home = NULL;
char as_uuid[37];
size_t n_env = 1;
}
if (arg_console_mode != CONSOLE_PIPE) {
+ _cleanup_close_ int master = -1;
_cleanup_free_ char *console = NULL;
/* Allocate a pty and make it available as /dev/console. */
#if HAVE_LIBCRYPTSETUP
crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL);
- crypt_set_debug_level(1);
+ if (DEBUG_LOGGING)
+ crypt_set_debug_level(CRYPT_DEBUG_ALL);
#endif
r = get_block_device_harder(mountpath, &devno);
umask(0022);
- if (argc != 1) {
- log_error("This program takes no arguments.");
- return -EINVAL;
- }
+ if (argc != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments.");
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0);
#include <sys/un.h>
#include "alloc-util.h"
+#include "main-func.h"
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
return 0;
}
-int main(int argc, char *argv[]) {
- _cleanup_free_ char *packet = NULL;
+static int run(int argc, char *argv[]) {
+ _cleanup_(erase_and_freep) char *packet = NULL;
_cleanup_close_ int fd = -1;
size_t length = 0;
int r;
log_setup_service();
- if (argc != 3) {
- log_error("Wrong number of arguments.");
- return EXIT_FAILURE;
- }
+ if (argc != 3)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments.");
if (streq(argv[1], "1")) {
_cleanup_string_free_erase_ char *line = NULL;
r = read_line(stdin, LONG_LINE_MAX, &line);
- if (r < 0) {
- log_error_errno(r, "Failed to read password: %m");
- goto finish;
- }
- if (r == 0) {
- log_error("Got EOF while reading password.");
- r = -EIO;
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to read password: %m");
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Got EOF while reading password.");
packet = strjoin("+", line);
- if (!packet) {
- r = log_oom();
- goto finish;
- }
+ if (!packet)
+ return log_oom();
length = 1 + strlen(line) + 1;
} else if (streq(argv[1], "0")) {
packet = strdup("-");
- if (!packet) {
- r = log_oom();
- goto finish;
- }
+ if (!packet)
+ return log_oom();
length = 1;
- } else {
- log_error("Invalid first argument %s", argv[1]);
- r = -EINVAL;
- goto finish;
- }
+ } else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Invalid first argument %s", argv[1]);
fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0) {
- r = log_error_errno(errno, "socket() failed: %m");
- goto finish;
- }
+ if (fd < 0)
+ return log_error_errno(errno, "socket() failed: %m");
- r = send_on_socket(fd, argv[2], packet, length);
-
-finish:
- explicit_bzero_safe(packet, length);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return send_on_socket(fd, argv[2], packet, length);
}
+
+DEFINE_MAIN_FUNCTION(run);
else if (c.exit_code > 0)
log_info("Main processes terminated with: code=%s/status=%s", sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status));
- if (c.inactive_enter_usec > 0 && c.inactive_enter_usec != USEC_INFINITY &&
- c.inactive_exit_usec > 0 && c.inactive_exit_usec != USEC_INFINITY &&
+ if (timestamp_is_set(c.inactive_enter_usec) &&
+ timestamp_is_set(c.inactive_exit_usec) &&
c.inactive_enter_usec > c.inactive_exit_usec) {
char ts[FORMAT_TIMESPAN_MAX];
log_info("Service runtime: %s", format_timespan(ts, sizeof(ts), c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC));
}
static int retrieve_key(key_serial_t serial, char ***ret) {
- _cleanup_free_ char *p = NULL;
- long m = 100, n;
+ size_t nfinal, m = 100;
char **l;
+ _cleanup_(erase_and_freep) char *pfinal = NULL;
assert(ret);
for (;;) {
+ _cleanup_(erase_and_freep) char *p = NULL;
+ long n;
+
p = new(char, m);
if (!p)
return -ENOMEM;
n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0);
if (n < 0)
return -errno;
- if (n < m)
+ if ((size_t) n < m) {
+ nfinal = (size_t) n;
+ pfinal = TAKE_PTR(p);
break;
-
- explicit_bzero_safe(p, m);
+ }
if (m > LONG_MAX / 2) /* overflow check */
return -ENOMEM;
m *= 2;
- if ((long) (size_t) m != m) /* make sure that this still fits if converted to size_t */
- return -ENOMEM;
-
- free(p);
}
- l = strv_parse_nulstr(p, n);
+ l = strv_parse_nulstr(pfinal, nfinal);
if (!l)
return -ENOMEM;
- explicit_bzero_safe(p, n);
-
*ret = l;
return 0;
}
static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) {
_cleanup_strv_free_erase_ char **l = NULL;
- _cleanup_free_ char *p = NULL;
+ _cleanup_(erase_and_freep) char *p = NULL;
key_serial_t serial;
size_t n;
int r;
return r;
serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING);
- explicit_bzero_safe(p, n);
if (serial == -1)
return -errno;
#include "device-nodes.h"
#include "device-util.h"
#include "dissect-image.h"
+#include "dm-util.h"
#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
}
}
-#if HAVE_LIBCRYPTSETUP
-static int deferred_remove(DecryptedPartition *p) {
- struct dm_ioctl dm = {
- .version = {
- DM_VERSION_MAJOR,
- DM_VERSION_MINOR,
- DM_VERSION_PATCHLEVEL
- },
- .data_size = sizeof(dm),
- .flags = DM_DEFERRED_REMOVE,
- };
-
- _cleanup_close_ int fd = -1;
-
- assert(p);
-
- /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() directly. */
-
- fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- if (strlen(p->name) > sizeof(dm.name))
- return -ENAMETOOLONG;
-
- strncpy(dm.name, p->name, sizeof(dm.name));
-
- if (ioctl(fd, DM_DEV_REMOVE, &dm))
- return -errno;
-
- return 0;
-}
-#endif
-
int decrypted_image_relinquish(DecryptedImage *d) {
#if HAVE_LIBCRYPTSETUP
if (p->relinquished)
continue;
- r = deferred_remove(p);
+ r = dm_deferred_remove(p->name);
if (r < 0)
return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name);
--- /dev/null
+#include <fcntl.h>
+#include <linux/dm-ioctl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#include "dm-util.h"
+#include "fd-util.h"
+#include "string-util.h"
+
+int dm_deferred_remove(const char *name) {
+
+ struct dm_ioctl dm = {
+ .version = {
+ DM_VERSION_MAJOR,
+ DM_VERSION_MINOR,
+ DM_VERSION_PATCHLEVEL
+ },
+ .data_size = sizeof(dm),
+ .flags = DM_DEFERRED_REMOVE,
+ };
+
+ _cleanup_close_ int fd = -1;
+
+ assert(name);
+
+ /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl()
+ * directly. */
+
+ if (strlen(name) >= sizeof(dm.name))
+ return -ENODEV; /* A device with a name longer than this cannot possibly exist */
+
+ fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ strncpy_exact(dm.name, name, sizeof(dm.name));
+
+ if (ioctl(fd, DM_DEV_REMOVE, &dm))
+ return -errno;
+
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+int dm_deferred_remove(const char *name);
#include "sd-id128.h"
+#include "efi/loader-features.h"
#include "time-util.h"
#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
-#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT (UINT64_C(1) << 0)
-#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1)
-#define EFI_LOADER_FEATURE_ENTRY_DEFAULT (UINT64_C(1) << 2)
-#define EFI_LOADER_FEATURE_ENTRY_ONESHOT (UINT64_C(1) << 3)
-#define EFI_LOADER_FEATURE_BOOT_COUNTING (UINT64_C(1) << 4)
-
#if ENABLE_EFI
bool is_efi_boot(void);
const union in_addr_union *destination,
unsigned destination_prefixlen) {
+ static const xt_chainlabel chain = "POSTROUTING";
_cleanup_(iptc_freep) struct xtc_handle *h = NULL;
struct ipt_entry *entry, *mask;
struct ipt_entry_target *t;
memset(mask, 0xFF, sz);
if (add) {
- if (iptc_check_entry("POSTROUTING", entry, (unsigned char*) mask, h))
+ if (iptc_check_entry(chain, entry, (unsigned char*) mask, h))
return 0;
if (errno != ENOENT) /* if other error than not existing yet, fail */
return -errno;
- if (!iptc_insert_entry("POSTROUTING", entry, 0, h))
+ if (!iptc_insert_entry(chain, entry, 0, h))
return -errno;
} else {
- if (!iptc_delete_entry("POSTROUTING", entry, (unsigned char*) mask, h)) {
+ if (!iptc_delete_entry(chain, entry, (unsigned char*) mask, h)) {
if (errno == ENOENT) /* if it's already gone, all is good! */
return 0;
uint16_t remote_port,
const union in_addr_union *previous_remote) {
+ static const xt_chainlabel chain_pre = "PREROUTING", chain_output = "OUTPUT";
_cleanup_(iptc_freep) struct xtc_handle *h = NULL;
struct ipt_entry *entry, *mask;
struct ipt_entry_target *t;
if (add) {
/* Add the PREROUTING rule, if it is missing so far */
- if (!iptc_check_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+ if (!iptc_check_entry(chain_pre, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -EINVAL;
- if (!iptc_insert_entry("PREROUTING", entry, 0, h))
+ if (!iptc_insert_entry(chain_pre, entry, 0, h))
return -errno;
}
if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
- if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+ if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -errno;
}
entry->ip.invflags = IPT_INV_DSTIP;
}
- if (!iptc_check_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+ if (!iptc_check_entry(chain_output, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -errno;
- if (!iptc_insert_entry("OUTPUT", entry, 0, h))
+ if (!iptc_insert_entry(chain_output, entry, 0, h))
return -errno;
}
if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) {
mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr;
- if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+ if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -errno;
}
}
}
} else {
- if (!iptc_delete_entry("PREROUTING", entry, (unsigned char*) mask, h)) {
+ if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -errno;
}
entry->ip.invflags = IPT_INV_DSTIP;
}
- if (!iptc_delete_entry("OUTPUT", entry, (unsigned char*) mask, h)) {
+ if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) {
if (errno != ENOENT)
return -errno;
}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+/* exit codes as defined in fsck(8) */
+enum {
+ FSCK_SUCCESS = 0,
+ FSCK_ERROR_CORRECTED = 1 << 0,
+ FSCK_SYSTEM_SHOULD_REBOOT = 1 << 1,
+ FSCK_ERRORS_LEFT_UNCORRECTED = 1 << 2,
+ FSCK_OPERATIONAL_ERROR = 1 << 3,
+ FSCK_USAGE_OR_SYNTAX_ERROR = 1 << 4,
+ FSCK_USER_CANCELLED = 1 << 5,
+ FSCK_SHARED_LIB_ERROR = 1 << 7,
+};
#include <unistd.h>
#include "alloc-util.h"
+#include "errno-util.h"
#include "escape.h"
#include "fd-util.h"
#include "io-util.h"
"Failed to store received data of size %zu "
"(in addition to existing %zu bytes with %zu filled): %s",
size, imp->size, imp->filled,
- strerror(ENOMEM));
+ strerror_safe(ENOMEM));
memcpy(imp->buf + imp->filled, data, size);
imp->filled += size;
int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
_cleanup_strv_free_ char **l = NULL;
char ***s = userdata;
- size_t i;
+ JsonVariant *e;
int r;
assert(variant);
if (!json_variant_is_array(variant))
return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name));
- for (i = 0; i < json_variant_elements(variant); i++) {
- JsonVariant *e;
-
- assert_se(e = json_variant_by_index(variant, i));
-
+ JSON_VARIANT_ARRAY_FOREACH(e, variant) {
if (!json_variant_is_string(e))
return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string.");
dev-setup.h
dissect-image.c
dissect-image.h
+ dm-util.c
+ dm-util.h
dns-domain.c
dns-domain.h
dropin.c
firewall-util.h
format-table.c
format-table.h
+ fsck-util.h
fstab-util.c
fstab-util.h
generator.c
usec_t t;
assert_return(v, -EINVAL);
- assert_return(!v->server, -ENOTTY);
if (v->state == VARLINK_DISCONNECTED)
return -ENOTCONN;
varlink_set_state(v, VARLINK_IDLE_SERVER);
- r = varlink_attach_event(v, server->event, server->event_priority);
- if (r < 0) {
- varlink_log_errno(v, r, "Failed to attach new connection: %m");
- v->fd = -1; /* take the fd out of the connection again */
- varlink_close(v);
- return r;
+ if (server->event) {
+ r = varlink_attach_event(v, server->event, server->event_priority);
+ if (r < 0) {
+ varlink_log_errno(v, r, "Failed to attach new connection: %m");
+ v->fd = -1; /* take the fd out of the connection again */
+ varlink_close(v);
+ return r;
+ }
}
if (ret)
return 0;
}
+int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end) {
+ unsigned lower, upper;
+ int r;
+
+ r = parse_range(p, &lower, &upper);
+ if (r < 0)
+ return r;
+
+ if (lower > VLANID_MAX || upper > VLANID_MAX || lower > upper)
+ return -EINVAL;
+
+ *vid = lower;
+ *vid_end = upper;
+ return 0;
+}
+
int config_parse_default_port_vlanid(
const char *unit,
const char *filename,
}
int parse_vlanid(const char *p, uint16_t *ret);
+int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end);
CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid);
CONFIG_PARSER_PROTOTYPE(config_parse_vlanid);
assert(nw);
assert(next);
- if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
+ if (timestamp_is_set(next->monotonic)) {
usec_t converted;
if (next->monotonic > nw->monotonic)
else
converted = nw->realtime - (nw->monotonic - next->monotonic);
- if (next->realtime != USEC_INFINITY && next->realtime > 0)
+ if (timestamp_is_set(next->realtime))
next_elapse = MIN(converted, next->realtime);
else
next_elapse = converted;
int r;
/**
- * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is found, and
- * sets:
+ * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is
+ * found, and sets:
* - the path to the unit in *ret_frament_path, if it exists on disk,
- * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins were found.
+ * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins
+ * were found.
*
- * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for some
- * reason (the latter only applies if we are going through the service manager)
+ * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for
+ * some reason (the latter only applies if we are going through the service manager).
*/
assert(unit_name);
r = 0;
goto not_found;
}
- if (!streq(load_state, "loaded"))
+ if (!STR_IN_SET(load_state, "loaded", "bad-setting"))
return -EKEYREJECTED;
r = sd_bus_get_property_string(
if (i->status_text)
printf(" Status: \"%s\"\n", i->status_text);
if (i->status_errno > 0)
- printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
+ printf(" Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno));
if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) {
char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX];
sd_notifyf(0, "STATUS=Failed to start up: %s\n"
"ERRNO=%i",
- strerror(errno),
+ strerror_safe(errno),
errno);
See sd_notifyf(3) for more information.
int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data);
int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data);
int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type);
+int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type);
int sd_netlink_message_exit_container(sd_netlink_message *m);
int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);
#include "alloc-util.h"
#include "macro.h"
#include "memory-util.h"
+#include "random-util.h"
#include "tests.h"
static void test_alloca(void) {
log_debug("z: %p", &z);
}
+static void test_auto_erase_memory(void) {
+ _cleanup_(erase_and_freep) uint8_t *p1, *p2;
+
+ assert_se(p1 = new(uint8_t, 1024));
+ assert_se(p2 = new(uint8_t, 1024));
+
+ genuine_random_bytes(p1, 1024, RANDOM_BLOCK);
+
+ /* before we exit the scope, do something with this data, so that the compiler won't optimize this away */
+ memcpy(p2, p1, 1024);
+ for (size_t i = 0; i < 1024; i++)
+ assert_se(p1[i] == p2[i]);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_memdup_multiply_and_greedy_realloc();
test_bool_assign();
test_cleanup_order();
+ test_auto_erase_memory();
return 0;
}
#include "alloc-util.h"
#include "calendarspec.h"
+#include "errno-util.h"
#include "string-util.h"
#include "util.h"
u = now(CLOCK_REALTIME);
r = calendar_spec_next_usec(c, u, &u);
- printf("Next: %s\n", r < 0 ? strerror(-r) : format_timestamp(buf, sizeof(buf), u));
+ printf("Next: %s\n", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof(buf), u));
calendar_spec_free(c);
assert_se(calendar_spec_from_string(p, &c) >= 0);
u = after;
r = calendar_spec_next_usec(c, after, &u);
- printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u));
+ printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u));
if (expect != (usec_t)-1)
assert_se(r >= 0 && u == expect);
else
assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0);
printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n);
- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u), u);
assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0);
- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(zaf, sizeof zaf, w), w);
assert_se(n < u);
assert_se(u <= n + USEC_PER_HOUR);
int r;
r = path_extract_filename(input, &k);
- log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror(-r), strnull(output), strerror(-ret));
+ log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror_safe(r), strnull(output), strerror_safe(ret));
assert_se(streq_ptr(k, output));
assert_se(r == ret);
}
#include <sys/types.h>
#include <unistd.h>
+#include "errno-util.h"
#include "fd-util.h"
#include "log.h"
#include "memory-util.h"
log_info("/= running system =/");
r = can_sleep("suspend");
- log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("hibernate");
- log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("hybrid-sleep");
- log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
r = can_sleep("suspend-then-hibernate");
- log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror(-r));
+ log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r));
}
int main(int argc, char* argv[]) {
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include <stdio.h>
#include <string.h>
#include "string-util.h"
assert_se(space_left == 10);
}
+static void test_sd_event_code_migration(void) {
+ char b[100 * DECIMAL_STR_MAX(unsigned) + 1];
+ char c[100 * DECIMAL_STR_MAX(unsigned) + 1], *p;
+ unsigned i;
+ size_t l;
+ int o;
+
+ for (i = o = 0; i < 100; i++)
+ o += snprintf(&b[o], sizeof(b) - o, "%u ", i);
+
+ p = c;
+ l = sizeof(c);
+ for (i = 0; i < 100; i++)
+ l = strpcpyf(&p, l, "%u ", i);
+
+ assert_se(streq(b, c));
+}
+
int main(int argc, char *argv[]) {
test_strpcpy();
test_strpcpyf();
test_strscpy();
test_strscpyl();
+ test_sd_event_code_migration();
+
return 0;
}
/* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
* there's no immediate need for action by the user. However, in the interest of making things less confusing
* to the user, let's still inform the user that these snippets should really be updated. */
-
- log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", fname, line, *path, n);
+ log_syntax(NULL, LOG_NOTICE, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n);
free_and_replace(*path, n);
}
static int send_passwords(const char *socket_name, char **passwords) {
- _cleanup_free_ char *packet = NULL;
+ _cleanup_(erase_and_freep) char *packet = NULL;
_cleanup_close_ int socket_fd = -1;
union sockaddr_union sa = {};
size_t packet_length = 1;
char **p, *d;
ssize_t n;
- int r, salen;
+ int salen;
assert(socket_name);
d = stpcpy(d, *p) + 1;
socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
- if (socket_fd < 0) {
- r = log_debug_errno(errno, "socket(): %m");
- goto finish;
- }
+ if (socket_fd < 0)
+ return log_debug_errno(errno, "socket(): %m");
n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, salen);
- if (n < 0) {
- r = log_debug_errno(errno, "sendto(): %m");
- goto finish;
- }
+ if (n < 0)
+ return log_debug_errno(errno, "sendto(): %m");
- r = (int) n;
-
-finish:
- explicit_bzero_safe(packet, packet_length);
- return r;
+ return (int) n;
}
static int parse_password(const char *filename, char **wall) {
%includes
%%
Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
-Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
-Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
-Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
-Match.Type, config_parse_strv, 0, offsetof(link_config, match_type)
+Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name)
+Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path)
+Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver)
+Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type)
+Match.Property, config_parse_match_property, 0, offsetof(link_config, match_property)
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions)
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions)
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions)
strv_free(link->match_driver);
strv_free(link->match_type);
strv_free(link->match_name);
+ strv_free(link->match_property);
condition_free_list(link->conditions);
free(link->description);
if (set_isempty(link->match_mac) && strv_isempty(link->match_path) &&
strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
- strv_isempty(link->match_name) && !link->conditions)
+ strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions)
log_warning("%s: No valid settings found in the [Match] section. "
"The file will match all interfaces. "
"If that is intended, please add OriginalName=* in the [Match] section.",
assert(ret);
LIST_FOREACH(links, link, ctx->links) {
- const char *address = NULL, *id_path = NULL, *id_net_driver = NULL, *devtype = NULL, *sysname = NULL;
-
- (void) sd_device_get_sysattr_value(device, "address", &address);
- (void) sd_device_get_property_value(device, "ID_PATH", &id_path);
- (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &id_net_driver);
- (void) sd_device_get_devtype(device, &devtype);
- (void) sd_device_get_sysname(device, &sysname);
-
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
- link->match_type, link->match_name,
- address ? ether_aton(address) : NULL,
- id_path,
- id_net_driver,
- devtype,
- sysname)) {
+ link->match_type, link->match_name, link->match_property,
+ device, NULL, NULL)) {
if (link->match_name) {
unsigned name_assign_type = NET_NAME_UNKNOWN;
(void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type);
if (name_assign_type == NET_NAME_ENUM && !strv_contains(link->match_name, "*")) {
- log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
- link->filename, sysname);
+ log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name",
+ link->filename);
*ret = link;
return 0;
} else if (name_assign_type == NET_NAME_RENAMED) {
- log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
- link->filename, sysname);
+ log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring",
+ link->filename);
continue;
}
}
- log_debug("Config file %s applies to device %s",
- link->filename, sysname);
+ log_device_debug(device, "Config file %s is applied", link->filename);
*ret = link;
return 0;
char **match_driver;
char **match_type;
char **match_name;
+ char **match_property;
LIST_HEAD(Condition, conditions);
char *description;
EOF
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cat >>$initdir/etc/fstab <<EOF
/dev/mapper/varcrypt /var ext4 defaults 0 1
EOF
- ) || return 1
+ )
ddebug "umount $TESTDIR/root/var"
umount $TESTDIR/root/var
cp test-jobs.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp test-journal.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp test-rlimits.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
dracut_install -o sesearch
dracut_install runcon
dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile
- ) || return 1
+ )
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
cp test-segfault.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
EOF
setup_testsuite
- ) || return 1
+ )
ln -s /etc/systemd/system/-.mount $initdir/etc/systemd/system/root.mount
mkdir -p $initdir/etc/systemd/system/local-fs.target.wants
EOF
setup_testsuite
- ) || return 1
+ )
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
EOF
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
# mask some services that we do not want to run in these tests
chmod 0755 $initdir/test-fail-on-restart.sh
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
chmod 0755 $initdir/test-socket-group.sh
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
chmod 0755 $initdir/test-nspawn.sh
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
chmod +x $initdir/test-machine-id-setup.sh
setup_testsuite
- ) || return 1
+ )
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
cp $BUILD_DIR/src/shared/libsystemd-shared-*.so ${initdir}/usr/lib
setup_testsuite
- ) || return 1
+ )
# mask some services that we do not want to run in these tests
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
# mask some services that we do not want to run in these tests
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
# mask some services that we do not want to run in these tests
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
EOF
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
# mask some services that we do not want to run in these tests
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
ddebug "umount $TESTDIR/root"
umount $TESTDIR/root
cp testsuite.sh $initdir/
setup_testsuite
- ) || return 1
+ )
setup_nspawn_root
ddebug "umount $TESTDIR/root"
Path=
Driver=
Type=
+Property=
Host=
Virtualization=
KernelCommandLine=
--- /dev/null
+[NetDev]
+Name=xfrm99
+Kind=xfrm
+
+[Xfrm]
+InterfaceId=7
+Independent=false
Key=
KeyFile=
Activate=
+[Xfrm]
+Independent=
+InterfaceId=
--- /dev/null
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm99
Architecture=
Path=
Name=
+Property=
Virtualization=
KernelCommandLine=
Host=
IPv6HopLimit=
IPForward=
IPv6Token=
+Xfrm=
Description=
VXLAN=
L2TP=
--- /dev/null
+[IPv6AcceptRA]
+BlackList=70:: 70::
\ No newline at end of file
set -x
-DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
-DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+DEFAULT_ASAN_OPTIONS=${ASAN_OPTIONS:-strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1}
+DEFAULT_UBSAN_OPTIONS=${UBSAN_OPTIONS:-print_stacktrace=1:print_summary=1:halt_on_error=1}
DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS"
# As right now bash is the PID 1, we can't expect PATH to have a sane value.
# some {rc,halt}.local scripts and programs are okay to not exist, the rest should
# also, plymouth is pulled in by rescue.service, but even there the exit code
# is ignored; as it's not present on some distros, don't fail if it doesn't exist
+ dinfo "Attempting to install $i"
inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "/bin/plymouth" == "$i" ]
done
)
# Install binary executable, and all shared library dependencies, if any.
inst_binary() {
local _bin _target
+
+ # In certain cases we might attempt to install a binary which is already
+ # present in the test image, yet it's missing from the host system.
+ # In such cases, let's check if the binary indeed exists in the image
+ # before doing any other chcecks. If it does, immediately return with
+ # success.
+ [[ $# -eq 1 && -e $initdir/$1 ]] && return 0
+
_bin=$(find_binary "$1") || return 1
_target=${2:-$_bin}
[[ -e $initdir/$_target ]] && return 0
--- /dev/null
+[Match]
+Name=dummy98
+Property=INTERFACE=hoge
+
+[Network]
+IPv6AcceptRA=false
--- /dev/null
+[Match]
+Name=dummy98
+Property=INTERFACE=dummy98
+
+[Network]
+IPv6AcceptRA=false
+Address=10.1.2.3/16
--- /dev/null
+[Match]
+Name=bridge99
+
+[Network]
+IPv6AcceptRA=false
+
+[BridgeVLAN]
+VLAN=4060-4094
--- /dev/null
+[Match]
+Name=test1
+
+[Network]
+IPv6AcceptRA=no
+Bridge=bridge99
+
+[BridgeVLAN]
+VLAN=4064-4094
--- /dev/null
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+
+[Route]
+Destination=192.168.5.0/24
+
+[Route]
+Destination=192.168.6.0/24
+
+[Route]
+Destination=192.168.7.0/24
+
+[DHCP]
+UseRoutes=no
--- /dev/null
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv4
+IPv6AcceptRA=no
+Address=192.168.5.250
wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
networkctl_bin='/usr/bin/networkctl'
use_valgrind=False
-enable_debug=False
+enable_debug=True
env = {}
asan_options=None
lsan_options=None
return f
+def expectedFailureIfLinkFileFieldIsNotSet():
+ def f(func):
+ support = False
+ rc = call('ip link add name dummy99 type dummy')
+ if rc == 0:
+ ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
+ support = True
+ call('ip link del dummy99')
+
+ if support:
+ return func
+ else:
+ return unittest.expectedFailure(func)
+
+ return f
+
def expectedFailureIfEthtoolDoesNotSupportDriver():
def f(func):
support = False
if os.path.exists(dnsmasq_log_file):
os.remove(dnsmasq_log_file)
-def start_networkd(sleep_sec=0, remove_state_files=True):
- if (remove_state_files and
- os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
- check_output('systemctl stop systemd-networkd')
+def remove_networkd_state_files():
+ if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
os.remove(os.path.join(networkd_runtime_directory, 'state'))
- check_output('systemctl start systemd-networkd')
- else:
- check_output('systemctl restart systemd-networkd')
+
+def stop_networkd(show_logs=True, remove_state_files=True):
+ if show_logs:
+ invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
+ check_output('systemctl stop systemd-networkd')
+ if show_logs:
+ print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
+ if remove_state_files:
+ remove_networkd_state_files()
+
+def start_networkd(sleep_sec=0):
+ check_output('systemctl start systemd-networkd')
if sleep_sec > 0:
time.sleep(sleep_sec)
+def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
+ stop_networkd(show_logs, remove_state_files)
+ start_networkd(sleep_sec)
+
def wait_online(links_with_operstate, timeout='20s', bool_any=False):
args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
if bool_any:
def setUp(self):
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_glob(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
self.assertRegex(output, 'MTU: 1600')
+ def test_type(self):
+ copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+ start_networkd()
+ wait_online(['test1:degraded'])
+
+ output = check_output(*networkctl_cmd, 'status', 'test1')
+ print(output)
+ self.assertRegex(output, 'Type: ether')
+
+ output = check_output(*networkctl_cmd, 'status', 'lo')
+ print(output)
+ self.assertRegex(output, 'Type: loopback')
+
+ @expectedFailureIfLinkFileFieldIsNotSet()
+ def test_udev_link_file(self):
+ copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
+ start_networkd()
+ wait_online(['test1:degraded'])
+
+ output = check_output(*networkctl_cmd, 'status', 'test1')
+ print(output)
+ self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link')
+ self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
+
+ output = check_output(*networkctl_cmd, 'status', 'lo')
+ print(output)
+ self.assertRegex(output, r'Link File: (?:/usr)/lib/systemd/network/99-default.link')
+ self.assertRegex(output, r'Network File: n/a')
+
@expectedFailureIfEthtoolDoesNotSupportDriver()
def test_udev_driver(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
'11-dummy.netdev',
'11-dummy.network',
'12-dummy.netdev',
+ '13-not-match-udev-property.network',
+ '14-match-udev-property.network',
'15-name-conflict-test.netdev',
'21-macvlan.netdev',
'21-macvtap.netdev',
def setUp(self):
remove_fou_ports(self.fou_ports)
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_fou_ports(self.fou_ports)
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_dropin_and_name_conflict(self):
copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
print(output)
self.assertRegex(output, '00:50:56:c0:00:28')
+ def test_match_udev_property(self):
+ copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
+ start_networkd()
+ wait_online(['dummy98:routable'])
+
+ output = check_output('networkctl status dummy98')
+ print(output)
+ self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
+
def test_wait_online_any(self):
copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
start_networkd()
def setUp(self):
remove_l2tp_tunnels(self.l2tp_tunnel_ids)
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_l2tp_tunnels(self.l2tp_tunnel_ids)
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
@expectedFailureIfModuleIsNotAvailable('l2tp_eth')
def test_l2tp_udp(self):
remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
remove_routes(self.routes)
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
remove_routes(self.routes)
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_address_static(self):
copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
for trial in range(3):
# Remove state files only first time
- start_networkd(0, remove_state_files=(trial == 0))
+ start_networkd()
wait_online(['test1:degraded', 'dummy98:degraded'])
time.sleep(1)
print(output)
self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
+ stop_networkd(remove_state_files=False)
+
@expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
def test_routing_policy_rule_port_range(self):
copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
- start_networkd()
+ restart_networkd()
wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dummy98')
def setUp(self):
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_bond_active_slave(self):
copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
'26-bridge.netdev',
'26-bridge-slave-interface-1.network',
'26-bridge-slave-interface-2.network',
+ '26-bridge-vlan-master.network',
+ '26-bridge-vlan-slave.network',
'bridge99-ignore-carrier-loss.network',
'bridge99.network']
def setUp(self):
remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
+
+ def test_bridge_vlan(self):
+ copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
+ '26-bridge.netdev', '26-bridge-vlan-master.network')
+ start_networkd()
+ wait_online(['test1:enslaved', 'bridge99:degraded'])
+
+ output = check_output('bridge vlan show dev test1')
+ print(output)
+ self.assertNotRegex(output, '4063')
+ for i in range(4064, 4095):
+ self.assertRegex(output, f'{i}')
+ self.assertNotRegex(output, '4095')
+
+ output = check_output('bridge vlan show dev bridge99')
+ print(output)
+ self.assertNotRegex(output, '4059')
+ for i in range(4060, 4095):
+ self.assertRegex(output, f'{i}')
+ self.assertNotRegex(output, '4095')
def test_bridge_property(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
def setUp(self):
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_lldp(self):
copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
def setUp(self):
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_ipv6_prefix_delegation(self):
warn_about_firewalld()
def setUp(self):
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_dhcp_server(self):
warn_about_firewalld()
'dhcp-client-listen-port.network',
'dhcp-client-route-metric.network',
'dhcp-client-route-table.network',
+ 'dhcp-client-use-routes-no.network',
'dhcp-client-vrf.network',
'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
+ 'dhcp-client-with-static-address.network',
'dhcp-client.network',
'dhcp-server-veth-peer.network',
'dhcp-v4-server-veth-peer.network',
def setUp(self):
stop_dnsmasq(dnsmasq_pid_file)
remove_links(self.links)
+ stop_networkd(show_logs=False)
def tearDown(self):
stop_dnsmasq(dnsmasq_pid_file)
remove_log_file()
remove_links(self.links)
remove_unit_from_networkd_path(self.units)
+ stop_networkd(show_logs=True)
def test_dhcp_client_ipv6_only(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
print(output)
self.assertRegex(output, '192.168.5.* dynamic')
+ def test_dhcp_client_with_static_address(self):
+ copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
+ 'dhcp-client-with-static-address.network')
+ start_networkd()
+ wait_online(['veth-peer:carrier'])
+ start_dnsmasq()
+ wait_online(['veth99:routable', 'veth-peer:routable'])
+
+ output = check_output('ip address show dev veth99 scope global')
+ print(output)
+ self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
+ self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
+
+ output = check_output('ip route show dev veth99')
+ print(output)
+ self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
+ self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
+ self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
+ self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
+
def test_dhcp_route_table_id(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
start_networkd()
print(output)
self.assertRegex(output, 'metric 24')
+ def test_dhcp_client_use_routes_no(self):
+ copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
+ 'dhcp-client-use-routes-no.network')
+ start_networkd()
+ wait_online(['veth-peer:carrier'])
+ start_dnsmasq(lease_time='2m')
+ wait_online(['veth99:routable', 'veth-peer:routable'])
+
+ output = check_output('ip address show dev veth99 scope global')
+ print(output)
+ self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
+
+ output = check_output('ip route show dev veth99')
+ print(output)
+ self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
+ self.assertRegex(output, r'192.168.5.0/24 proto static')
+ self.assertRegex(output, r'192.168.6.0/24 proto static')
+ self.assertRegex(output, r'192.168.7.0/24 proto static')
+
+ # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
+ print('Wait for the dynamic address to be renewed')
+ time.sleep(125)
+
+ wait_online(['veth99:routable'])
+
+ output = check_output('ip route show dev veth99')
+ print(output)
+ self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
+ self.assertRegex(output, r'192.168.5.0/24 proto static')
+ self.assertRegex(output, r'192.168.6.0/24 proto static')
+ self.assertRegex(output, r'192.168.7.0/24 proto static')
+
def test_dhcp_keep_configuration_dhcp(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
start_networkd()
print(output)
self.assertRegex(output, r'192.168.5.*')
- start_networkd()
+ restart_networkd()
wait_online(['veth-peer:routable'])
output = check_output('ip address show dev veth99 scope global')
# When networkd started, the links are already configured, so let's wait for 5 seconds
# the links to be re-configured.
- start_networkd(5)
+ restart_networkd(5)
wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip -4 address show dev veth99 scope global')
}
+sub cleanup {
+ system("rm", "-rf", "$udev_run");
+ system("umount", "$udev_tmpfs");
+ rmdir($udev_tmpfs);
+}
+
# only run if we have root permissions
# due to mknod restrictions
if (!($<==0)) {
if (!udev_setup()) {
warn "Failed to set up the environment, skipping the test";
+ cleanup();
exit($EXIT_TEST_SKIP);
}
if (system($udev_bin, "check")) {
warn "$udev_bin failed to set up the environment, skipping the test";
+ cleanup();
exit($EXIT_TEST_SKIP);
}
print "$error errors occurred\n\n";
-# cleanup
-system("rm", "-rf", "$udev_run");
-system("umount", "$udev_tmpfs");
-rmdir($udev_tmpfs);
+cleanup();
if ($error > 0) {
exit(1);
sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
sudo apt-get update -y
sudo apt-get build-dep systemd -y
-sudo apt-get install -y ninja-build python3-pip python3-setuptools
+sudo apt-get install -y ninja-build python3-pip python3-setuptools quota
pip3 install meson
cd $REPO_ROOT
python3-pyparsing
python3-setuptools
qemu-system-x86
+ quota
strace
unifont
util-linux)
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
SystemCallFilter=@system-service @mount
+SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
LockPersonality=yes
IPAddressDeny=any