</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>custom</option></term>
+ <listitem><para>If <literal>DUIDType=custom</literal>, then the <literal>DUIDRawData=</literal> value will
+ used be as custom identifier. If <literal>DUIDType=custom</literal> is specified then the
+ <literal>DUIDRawData=</literal> key is mandatory. Note it applies only on DHCPv6 clients.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>uuid</option></term>
<listitem><para>If <literal>DUIDType=uuid</literal>, and <varname>DUIDRawData=</varname> is not set,
<variablelist>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
+
+ <varlistentry>
+ <term><option>-c</option></term>
+ <term><option>--continuous</option></term>
+
+ <listitem><para> Used to make systemd-bsod wait continuously for changes in the
+ journal's status if doesn't find any emergency messages on initial attempt.</para></listitem>
+ </varlistentry>
</variablelist>
+
</refsect1>
<refsect1>
use <option>--read-only</option> to switch to read-only operation. The invoked process will have the
<varname>$SYSTEMD_DISSECT_ROOT</varname> environment variable set, containing the absolute path name
of the temporary mount point, i.e. the same directory that is set as the current working
- directory.</para></listitem>
+ directory. It will also have the <varname>$SYSTEMD_DISSECT_DEVICE</varname> environment variable set,
+ containing the absolute path name of the loop device the image was attached to.</para></listitem>
</varlistentry>
<varlistentry>
_exit(EXIT_FAILURE);
}
+ if (setenv("SYSTEMD_DISSECT_DEVICE", d->node, /* overwrite= */ true) < 0) {
+ log_error_errno(errno, "Failed to set $SYSTEMD_DISSECT_DEVICE: %m");
+ _exit(EXIT_FAILURE);
+ }
+
if (strv_isempty(arg_argv)) {
const char *sh;
#include "sysctl-util.h"
#include "terminal-util.h"
+static bool arg_continuous = false;
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
"as a string and a QR code.\n\n%s"
" -h --help Show this help\n"
" --version Show package version\n"
+ " -c --continuous Make systemd-bsod wait continuously\n"
+ "for changes in the journal\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
if (r < 0)
return log_error_errno(r, "Failed to seek to start of jornal: %m");
- r = sd_journal_next(j);
- if (r < 0)
- return log_error_errno(r, "Failed to read next journal entry: %m");
- if (r == 0) {
- log_debug("No emergency level entries in the journal");
- *ret = NULL;
- return 0;
+ for(;;) {
+ r = sd_journal_next(j);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read next journal entry: %m");
+ if (r > 0)
+ break;
+
+ if (!arg_continuous) {
+ log_debug("No emergency level entries in the journal");
+ *ret = NULL;
+ return 0;
+ }
+
+ r = sd_journal_wait(j, (uint64_t) -1);
+ if (r < 0)
+ return log_error_errno(r, "Failed to wait for changes: %m");
+
+ continue;
}
r = sd_journal_get_data(j, "MESSAGE", &d, &l);
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
+ { "continuous", no_argument, NULL, 'c' },
{}
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hc", options, NULL)) >= 0)
switch (c) {
case ARG_VERSION:
return version();
+ case 'c':
+ arg_continuous = true;
+ break;
+
case '?':
return -EINVAL;
threads,
],
},
+ libexec_template + {
+ 'name' : 'systemd-bsod',
+ 'conditions' : ['HAVE_QRENCODE'],
+ 'sources' : files('bsod.c'),
+ 'link_with' : libshared,
+ 'dependencies' : libqrencode,
+ },
executable_template + {
'name' : 'systemd-cat',
'public' : true,
threads,
],
},
- executable_template + {
- 'name' : 'systemd-bsod',
- 'conditions' : ['HAVE_QRENCODE'],
- 'public' : true,
- 'sources' : files('bsod.c'),
- 'link_with' : libshared,
- 'dependencies' : libqrencode,
- },
journal_test_template + {
'sources' : files('test-journal-append.c'),
'type' : 'manual',
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
static const char * const duid_type_table[_DUID_TYPE_MAX] = {
- [DUID_TYPE_LLT] = "DUID-LLT",
- [DUID_TYPE_EN] = "DUID-EN/Vendor",
- [DUID_TYPE_LL] = "DUID-LL",
- [DUID_TYPE_UUID] = "UUID",
+ [DUID_TYPE_LLT] = "DUID-LLT",
+ [DUID_TYPE_EN] = "DUID-EN/Vendor",
+ [DUID_TYPE_LL] = "DUID-LL",
+ [DUID_TYPE_UUID] = "UUID",
+ [DUID_TYPE_CUSTOM] = "Custom",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(duid_type, DUIDType);
DUID_TYPE_EN = 2,
DUID_TYPE_LL = 3,
DUID_TYPE_UUID = 4,
+ DUID_TYPE_CUSTOM = 5,
_DUID_TYPE_MAX,
_DUID_TYPE_INVALID = -EINVAL,
} DUIDType;
log_dhcp6_client(client, "Using DUID of type %i of incorrect length, proceeding.", duid_type);
}
- client->duid.type = htobe16(duid_type);
- memcpy(&client->duid.raw.data, duid, duid_len);
- client->duid_len = sizeof(client->duid.type) + duid_len;
-
+ if (duid_type == DUID_TYPE_CUSTOM) {
+ memcpy(&client->duid, duid, duid_len);
+ client->duid_len = duid_len;
+ } else {
+ client->duid.type = htobe16(duid_type);
+ memcpy(&client->duid.raw.data, duid, duid_len);
+ client->duid_len = sizeof(client->duid.type) + duid_len;
+ }
} else {
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
client->test_mode, &client->duid, &client->duid_len);
DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType);
static const char* const duid_type_table[_DUID_TYPE_MAX] = {
- [DUID_TYPE_LLT] = "link-layer-time",
- [DUID_TYPE_EN] = "vendor",
- [DUID_TYPE_LL] = "link-layer",
- [DUID_TYPE_UUID] = "uuid",
+ [DUID_TYPE_LLT] = "link-layer-time",
+ [DUID_TYPE_EN] = "vendor",
+ [DUID_TYPE_LL] = "link-layer",
+ [DUID_TYPE_UUID] = "uuid",
+ [DUID_TYPE_CUSTOM] = "custom",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType);
}
duid = link_get_dhcp6_duid(link);
+
+ if (duid->type == DUID_TYPE_CUSTOM && duid->raw_data_len == 0)
+ return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL),
+ "DHCPv6 CLIENT: Missing DUID Raw Data as duid type set to 'custom': %m");
+
if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time);
else
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=veth99
+
+[Network]
+DHCP=ipv6
+IPv6Token=::1a:2b:3c:4d
+
+[Route]
+Gateway=_ipv6ra
+Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
+
+[DHCPv6]
+DUIDType=custom
+DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00
self.assertIn('DHCPREPLY(veth-peer)', output)
self.assertNotIn('rapid-commit', output)
+ def test_dhcp_client_ipv6_only_with_custom_client_identifier(self):
+ copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only-custom-client-identifier.network')
+
+ start_networkd()
+ self.wait_online(['veth-peer:carrier'])
+ start_dnsmasq()
+ self.wait_online(['veth99:routable', 'veth-peer:routable'])
+
+ # checking address
+ output = check_output('ip address show dev veth99 scope global')
+ print(output)
+ self.assertRegex(output, r'inet6 2600::[0-9a-f:]*/128 scope global dynamic noprefixroute')
+ self.assertNotIn('192.168.5', output)
+
+ # checking semi-static route
+ output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
+ print(output)
+ self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
+
+ # Confirm that ipv6 token is not set in the kernel
+ output = check_output('ip token show dev veth99')
+ print(output)
+ self.assertRegex(output, 'token :: dev veth99')
+
+ print('## dnsmasq log')
+ output = read_dnsmasq_log_file()
+ print(output)
+ self.assertIn('DHCPSOLICIT(veth-peer) 00:00:ab:11:f9:2a:c2:77:29:f9:5c:00', output)
+ self.assertNotIn('DHCPADVERTISE(veth-peer)', output)
+ self.assertNotIn('DHCPREQUEST(veth-peer)', output)
+ self.assertIn('DHCPREPLY(veth-peer)', output)
+ self.assertIn('sent size: 0 option: 14 rapid-commit', output)
+
+ stop_dnsmasq()
+
def test_dhcp_client_ipv4_only(self):
copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
'conditions' : ['ENABLE_INITRD'],
'symlinks' : ['initrd.target.wants/'],
},
+ {
+ 'file' : 'systemd-bsod.service.in',
+ 'conditions' : ['HAVE_QRENCODE','ENABLE_INITRD'],
+ 'symlinks' : ['initrd.target.wants/'],
+ },
{
'file' : 'initrd-cleanup.service',
'conditions' : ['ENABLE_INITRD'],
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# This file is part of systemd.
+#
+# 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.
+
+[Unit]
+Description=Displays emergency message full screen.
+Documentation=man:systemd-bsod(8)
+ConditionVirtualization=no
+DefaultDependencies=no
+Conflicts=shutdown.target
+Before=shutdown.target
+After=systemd-battery-check.service
+
+[Service]
+RemainAfterExit=yes
+ExecStart={{LIBEXECDIR}}/systemd-bsod --continuous