1
0
mirror of https://github.com/systemd/systemd synced 2026-03-13 16:44:48 +01:00

Compare commits

...

19 Commits

Author SHA1 Message Date
Alexander Sverdlin
4e947bd049 systemd-coredump: Add conflict with shutdown.target
Otherwise a coredump started at the inconvinient moment can stop
shutdown.target leaving the system in a halfway-down state:

Pulling in shutdown.target/start from systemd-poweroff.service/start
Added job shutdown.target/start to transaction.
...
Keeping job shutdown.target/start because of systemd-poweroff.service/start
...
[  OK  ] Stopped target Remote File Systems.
shutdown.target: starting held back, waiting for: systemd-networkd.socket
sysinit.target: stopping held back, waiting for: remount_tmp.service
systemd-coredump.socket: Incoming traffic
...
systemd-coredump@0-243-0.service: Trying to enqueue job systemd-coredump@0-243-0.service/start/replace
Added job systemd-coredump@0-243-0.service/start to transaction.
Pulling in systemd-journald.socket/start from systemd-coredump@0-243-0.service/start
Added job systemd-journald.socket/start to transaction.
Pulling in system.slice/start from systemd-journald.socket/start
Added job system.slice/start to transaction.
Pulling in -.slice/start from system.slice/start
Added job -.slice/start to transaction.
Pulling in system-systemd\x2dcoredump.slice/start from systemd-coredump@0-243-0.service/start
Added job system-systemd\x2dcoredump.slice/start to transaction.
Pulling in system.slice/start from system-systemd\x2dcoredump.slice/start
Pulling in shutdown.target/stop from system-systemd\x2dcoredump.slice/start
Added job shutdown.target/stop to transaction.
...
Keeping job systemd-poweroff.service/stop because of umount.target/stop
Keeping job shutdown.target/stop because of systemd-coredump@0-243-0.service/start
2021-04-29 21:45:23 +02:00
Lennart Poettering
c3a5240e3a
Merge pull request #19458 from yuwata/network-route-remove
network: fix route removal logic a bit
2021-04-29 21:39:30 +02:00
Viktor Mihajlovski
5a7eb46c02 udev: allow onboard index up to 65535
The maximum allowed value of the sysfs device index entry was limited to
16383 (2^14-1) to avoid the generation of unreasonable onboard interface
names.
For s390 the index can assume a value of up to 65535 (2^16-1) which is
now allowed depending on the new naming flag NAMING_16BIT_INDEX.
Larger index values are considered unreasonable and remain to be
ignored.
2021-04-29 21:38:21 +02:00
Lennart Poettering
34bcc67681
Merge pull request #19451 from poettering/hostnamed-json
hostnamed: add JSON output to hostnamectl
2021-04-29 21:37:52 +02:00
Lennart Poettering
97a7243650 man: document new dbus method 2021-04-29 16:39:09 +02:00
Lennart Poettering
ac8a4f6b78 hostnamectl: add --json= switch for JSON output
This wraps the new Describe() bus call of hostnamed.
2021-04-29 16:39:09 +02:00
Lennart Poettering
7ecead8f08 hostnamed: add Describe() call to hostnamed, returning all props a JSON 2021-04-29 16:39:09 +02:00
Lennart Poettering
f8da67cdf2 hostnamed: drop unused enums 2021-04-29 16:39:09 +02:00
Lennart Poettering
f2a434a5b8 hostnamed: split out how we determine the hostname a bit
No changes in code, just some splitting out of code we want to use
elsewhere soon.
2021-04-29 16:39:09 +02:00
Lennart Poettering
61d44b6beb hostnamed: refactor vendor/model querying a bit, reuse function 2021-04-29 16:39:09 +02:00
Lennart Poettering
c52e295d68 hostnamed: use byte array when we need a byte array
it's more corect this way, but shouldn#t change a thing binary-wise
2021-04-29 16:39:09 +02:00
Lennart Poettering
66ee229879 hostnamed: retrieve product UUID after authentication, not before 2021-04-29 16:39:09 +02:00
Lennart Poettering
b4be4ff8ae id128-util: use common implementation of helper to get/validate product ID 2021-04-29 16:39:09 +02:00
Yu Watanabe
3c7f1c0757 network: do not set nexthop ID, gateway, and multipath routes simultaneously
See kernel's rtm_to_fib_config() in net/ipv4/fib_frontend.c and
rtm_to_fib6_config() in net/ipv6/route.c.

Note that if both gateway and multipath routes are specified, then
kernel ignores gateway. So, strictly speaking, setting both gateway and
multipath routes is allowed by kernel. But such situation is mostly
user's misconfiguration. Let's refuse it.

Note that the conditions newly added in route_configure() are redundant,
as all static configurations are already verified in
route_section_verify(), and dynamic configurations do not set
nexthop_id or multipath routes. Just for safety.
2021-04-29 22:54:40 +09:00
Yu Watanabe
8a9ce525d1 network: do not remove reject type routes more than once
Usually, removing non-existing addresses, routes, and etc, are safe.
However, when multiple interfaces lost their carriers simultaneously,
then manager_drop_routes() and manager_drop_nexthop() are called multiple
times. If a route with a blackhole nexthop is removed in that process,
the later removal requests of the route fail with -EINVAL, rathar
than -ESRCH, as the corresponding nexthop does not exist anymore.

So, let's not remove routes which managed by Manager more than once.
2021-04-29 09:11:36 +09:00
Yu Watanabe
c3fa1257da network: do not set route type on specific route removal 2021-04-29 09:08:55 +09:00
Yu Watanabe
fd221544f2 network: unify log_link_message_full_errno() and log_message_warning_errno()
This also introduces log_message_error_errno() or friends.
2021-04-29 09:07:42 +09:00
Yu Watanabe
e558d4f47a network: dhcp4: downgrade log level when interface is removed 2021-04-29 08:58:13 +09:00
Yu Watanabe
4cbd379e01 network: drop meaningless bitfield specifiers 2021-04-29 08:58:13 +09:00
19 changed files with 393 additions and 144 deletions

View File

@ -195,6 +195,7 @@
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="json" />
</variablelist>
</refsect1>

View File

@ -58,6 +58,7 @@ node /org/freedesktop/hostname1 {
in b interactive);
GetProductUUID(in b interactive,
out ay uuid);
Describe(out s UNNAMED);
properties:
readonly s Hostname = '...';
readonly s StaticHostname = '...';
@ -118,6 +119,8 @@ node /org/freedesktop/hostname1 {
<variablelist class="dbus-method" generated="True" extra-ref="GetProductUUID()"/>
<variablelist class="dbus-method" generated="True" extra-ref="Describe()"/>
<variablelist class="dbus-property" generated="True" extra-ref="Hostname"/>
<variablelist class="dbus-property" generated="True" extra-ref="StaticHostname"/>
@ -232,6 +235,17 @@ node /org/freedesktop/hostname1 {
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>3</manvolnum></citerefentry>
for that. For more information on these files and syscalls see the respective man pages.</para>
<para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
<varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
(e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
reported by <citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
<varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
<varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
<varname>HOME_URL=</varname> fields from
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
purpose of those properties is to allow remote clients to access this information over D-Bus. Local
clients can access the information directly.</para>
<refsect2>
<title>Methods</title>
@ -261,22 +275,12 @@ node /org/freedesktop/hostname1 {
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
the semantics of those settings.</para>
<para><function>GetProductUUID()</function> returns the "product uuid" as exposed by the kernel based
<para><function>GetProductUUID()</function> returns the "product UUID" as exposed by the kernel based
on DMI information in <filename>/sys/class/dmi/id/product_uuid</filename>. Reading the file directly
requires root privileges, and this method allows access to unprivileged clients through the polkit
framework.</para>
<para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
<varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
(e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
reported by
<citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
<varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
<varname>HomeURL</varname> expose the <varname>PRETTY_NAME=</varname>, <varname>CPE_NAME=</varname> and
<varname>HOME_URL=</varname> fields from
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>. The
purpose of those properties is to allow remote clients to access this information over D-Bus. Local
clients can access the information directly.</para>
<para><function>Describe()</function> returns a JSON representation of all properties in one.</para>
</refsect2>
<refsect2>

View File

@ -376,7 +376,12 @@
of the <filename>function_id</filename> device attribute. This attribute is now used to build the
<varname>ID_NET_NAME_SLOT</varname>. Before that, all slot names were parsed as decimal
numbers, which could either result in an incorrect value of the <varname>ID_NET_NAME_SLOT</varname>
property or none at all.</para></listitem>
property or none at all.</para>
<para>Some firmware and hypervisor implementations report unreasonable high numbers for the onboard
index. To prevent the generation of bogus onbard interface names, index numbers greater than 16381
(2^14-1) were ignored. For s390 PCI devices index values up to 65535 (2^16-1) are valid. To account
for that, the limit is increased to now 65535.</para></listitem>
</varlistentry>
</variablelist>

View File

@ -17,7 +17,9 @@
#include "format-table.h"
#include "hostname-setup.h"
#include "hostname-util.h"
#include "json.h"
#include "main-func.h"
#include "parse-argument.h"
#include "pretty-print.h"
#include "spawn-polkit-agent.h"
#include "terminal-util.h"
@ -30,6 +32,7 @@ static char *arg_host = NULL;
static bool arg_transient = false;
static bool arg_pretty = false;
static bool arg_static = false;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
typedef struct StatusInfo {
const char *hostname;
@ -317,6 +320,37 @@ static int show_all_names(sd_bus *bus) {
static int show_status(int argc, char **argv, void *userdata) {
sd_bus *bus = userdata;
int r;
if (arg_json_format_flags != JSON_FORMAT_OFF) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
const char *text = NULL;
r = sd_bus_call_method(
bus,
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
"Describe",
&error,
&reply,
NULL);
if (r < 0)
return log_error_errno(r, "Could not get description: %s", bus_error_message(&error, r));
r = sd_bus_message_read(reply, "s", &text);
if (r < 0)
return bus_log_parse_error(r);
r = json_parse(text, 0, &v, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse JSON: %m");
json_variant_dump(v, arg_json_format_flags, NULL, NULL);
return 0;
}
if (arg_pretty || arg_static || arg_transient) {
const char *attr;
@ -489,6 +523,8 @@ static int help(void) {
" --transient Only set transient hostname\n"
" --static Only set static hostname\n"
" --pretty Only set pretty hostname\n"
" --json=pretty|short|off\n"
" Generate JSON output\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -509,7 +545,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_ASK_PASSWORD,
ARG_TRANSIENT,
ARG_STATIC,
ARG_PRETTY
ARG_PRETTY,
ARG_JSON,
};
static const struct option options[] = {
@ -521,10 +558,11 @@ static int parse_argv(int argc, char *argv[]) {
{ "host", required_argument, NULL, 'H' },
{ "machine", required_argument, NULL, 'M' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{ "json", required_argument, NULL, ARG_JSON },
{}
};
int c;
int c, r;
assert(argc >= 0);
assert(argv);
@ -565,6 +603,13 @@ static int parse_argv(int argc, char *argv[]) {
arg_ask_password = false;
break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case '?':
return -EINVAL;

View File

@ -20,6 +20,7 @@
#include "hostname-setup.h"
#include "hostname-util.h"
#include "id128-util.h"
#include "json.h"
#include "main-func.h"
#include "missing_capability.h"
#include "nscd-flush.h"
@ -40,6 +41,8 @@
#define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
/* Properties we cache are indexed by an enum, to make invalidation easy and systematic (as we can iterate
* through them all, and they are uniformly strings). */
enum {
/* Read from /etc/hostname */
PROP_STATIC_HOSTNAME,
@ -51,9 +54,6 @@ enum {
PROP_DEPLOYMENT,
PROP_LOCATION,
PROP_HARDWARE_VENDOR,
PROP_HARDWARE_MODEL,
/* Read from /etc/os-release (or /usr/lib/os-release) */
PROP_OS_PRETTY_NAME,
PROP_OS_CPE_NAME,
@ -449,6 +449,41 @@ static int context_write_data_machine_info(Context *c) {
return 0;
}
static int get_dmi_data(const char *database_key, const char *regular_key, char **ret) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
_cleanup_free_ char *b = NULL;
const char *s = NULL;
int r;
r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
if (r < 0)
return log_debug_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
if (database_key)
(void) sd_device_get_property_value(device, database_key, &s);
if (!s && regular_key)
(void) sd_device_get_property_value(device, regular_key, &s);
if (s) {
b = strdup(s);
if (!b)
return -ENOMEM;
}
if (ret)
*ret = TAKE_PTR(b);
return !!s;
}
static int get_hardware_vendor(char **ret) {
return get_dmi_data("ID_VENDOR_FROM_DATABASE", "ID_VENDOR", ret);
}
static int get_hardware_model(char **ret) {
return get_dmi_data("ID_MODEL_FROM_DATABASE", "ID_MODEL", ret);
}
static int property_get_hardware_vendor(
sd_bus *bus,
const char *path,
@ -457,20 +492,11 @@ static int property_get_hardware_vendor(
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *hardware_vendor = NULL;
int r;
r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
if (r < 0) {
log_warning_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
return sd_bus_message_append(reply, "s", NULL);
}
_cleanup_free_ char *vendor = NULL;
if (sd_device_get_property_value(device, "ID_VENDOR_FROM_DATABASE", &hardware_vendor) < 0)
(void) sd_device_get_property_value(device, "ID_VENDOR", &hardware_vendor);
return sd_bus_message_append(reply, "s", hardware_vendor);
(void) get_hardware_vendor(&vendor);
return sd_bus_message_append(reply, "s", vendor);
}
static int property_get_hardware_model(
@ -481,20 +507,11 @@ static int property_get_hardware_model(
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *hardware_model = NULL;
int r;
r = sd_device_new_from_syspath(&device, "/sys/class/dmi/id");
if (r < 0) {
log_warning_errno(r, "Failed to open /sys/class/dmi/id device, ignoring: %m");
return sd_bus_message_append(reply, "s", NULL);
}
_cleanup_free_ char *model = NULL;
if (sd_device_get_property_value(device, "ID_MODEL_FROM_DATABASE", &hardware_model) < 0)
(void) sd_device_get_property_value(device, "ID_MODEL", &hardware_model);
return sd_bus_message_append(reply, "s", hardware_model);
(void) get_hardware_model(&model);
return sd_bus_message_append(reply, "s", model);
}
static int property_get_hostname(
@ -548,13 +565,46 @@ static int property_get_default_hostname(
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *hn = get_default_hostname();
_cleanup_free_ char *hn = NULL;
hn = get_default_hostname();
if (!hn)
return log_oom();
return sd_bus_message_append(reply, "s", hn);
}
static void context_determine_hostname_source(Context *c) {
char hostname[HOST_NAME_MAX + 1] = {};
_cleanup_free_ char *fallback = NULL;
int r;
assert(c);
if (c->hostname_source >= 0)
return;
(void) get_hostname_filtered(hostname);
if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
c->hostname_source = HOSTNAME_STATIC;
else {
/* If the hostname was not set by us, try to figure out where it came from. If we set it to
* the default hostname, the file will tell us. We compare the string because it is possible
* that the hostname was set by an older version that had a different fallback, in the
* initramfs or before we reexecuted. */
r = read_one_line_file("/run/systemd/default-hostname", &fallback);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
if (streq_ptr(fallback, hostname))
c->hostname_source = HOSTNAME_DEFAULT;
else
c->hostname_source = HOSTNAME_TRANSIENT;
}
}
static int property_get_hostname_source(
sd_bus *bus,
const char *path,
@ -565,36 +615,10 @@ static int property_get_hostname_source(
sd_bus_error *error) {
Context *c = userdata;
int r;
assert(c);
context_read_etc_hostname(c);
if (c->hostname_source < 0) {
char hostname[HOST_NAME_MAX + 1] = {};
_cleanup_free_ char *fallback = NULL;
(void) get_hostname_filtered(hostname);
if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
c->hostname_source = HOSTNAME_STATIC;
else {
/* If the hostname was not set by us, try to figure out where it came from. If we set
* it to the default hostname, the file will tell us. We compare the string because
* it is possible that the hostname was set by an older version that had a different
* fallback, in the initramfs or before we reexecuted. */
r = read_one_line_file("/run/systemd/default-hostname", &fallback);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read /run/systemd/default-hostname, ignoring: %m");
if (streq_ptr(fallback, hostname))
c->hostname_source = HOSTNAME_DEFAULT;
else
c->hostname_source = HOSTNAME_TRANSIENT;
}
}
context_determine_hostname_source(c);
return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
}
@ -932,28 +956,12 @@ static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *
static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Context *c = userdata;
bool has_uuid = false;
int interactive, r;
sd_id128_t uuid;
assert(m);
assert(c);
r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
if (r == -ENOENT)
r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid);
if (r < 0)
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read product UUID, ignoring: %m");
else if (sd_id128_is_null(uuid) || sd_id128_is_allf(uuid))
log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(uuid));
else
has_uuid = true;
if (!has_uuid)
return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
"Failed to read product UUID from firmware.");
r = sd_bus_message_read(m, "b", &interactive);
if (r < 0)
return r;
@ -972,11 +980,125 @@ static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_err
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = id128_get_product(&uuid);
if (r < 0) {
if (r == -EADDRNOTAVAIL)
log_debug_errno(r, "DMI product UUID is all 0x00 or all 0xFF, ignoring.");
else
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
"Failed to read product UUID, ignoring: %m");
return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID,
"Failed to read product UUID from firmware.");
}
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return r;
r = sd_bus_message_append_array(reply, 'y', &uuid, sizeof(uuid));
r = sd_bus_message_append_array(reply, 'y', uuid.bytes, sizeof(uuid.bytes));
if (r < 0)
return r;
return sd_bus_send(NULL, reply, NULL);
}
static int method_describe(sd_bus_message *m, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, *text = NULL, *vendor = NULL, *model = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
sd_id128_t product_uuid = SD_ID128_NULL;
const char *chassis = NULL;
Context *c = userdata;
bool privileged;
struct utsname u;
int r;
assert(m);
assert(c);
r = bus_verify_polkit_async(
m,
CAP_SYS_ADMIN,
"org.freedesktop.hostname1.get-product-uuid",
NULL,
false,
UID_INVALID,
&c->polkit_registry,
NULL);
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
/* We ignore all authentication errors here, since most data is unprivileged, the one exception being
* the product ID which we'll check explicitly. */
privileged = r > 0;
context_read_etc_hostname(c);
context_read_machine_info(c);
context_read_os_release(c);
context_determine_hostname_source(c);
r = gethostname_strict(&hn);
if (r < 0) {
if (r != -ENXIO)
return log_error_errno(r, "Failed to read local host name: %m");
hn = get_default_hostname();
if (!hn)
return log_oom();
}
dhn = get_default_hostname();
if (!dhn)
return log_oom();
if (isempty(c->data[PROP_ICON_NAME]))
in = context_fallback_icon_name(c);
if (isempty(c->data[PROP_CHASSIS]))
chassis = fallback_chassis();
assert_se(uname(&u) >= 0);
(void) get_hardware_vendor(&vendor);
(void) get_hardware_model(&model);
if (privileged) /* The product UUID is only available to privileged clients */
id128_get_product(&product_uuid);
r = json_build(&v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("Hostname", JSON_BUILD_STRING(hn)),
JSON_BUILD_PAIR("StaticHostname", JSON_BUILD_STRING(c->data[PROP_STATIC_HOSTNAME])),
JSON_BUILD_PAIR("PrettyHostname", JSON_BUILD_STRING(c->data[PROP_PRETTY_HOSTNAME])),
JSON_BUILD_PAIR("DefaultHostname", JSON_BUILD_STRING(dhn)),
JSON_BUILD_PAIR("HostnameSource", JSON_BUILD_STRING(hostname_source_to_string(c->hostname_source))),
JSON_BUILD_PAIR("IconName", JSON_BUILD_STRING(in ?: c->data[PROP_ICON_NAME])),
JSON_BUILD_PAIR("Chassis", JSON_BUILD_STRING(chassis ?: c->data[PROP_CHASSIS])),
JSON_BUILD_PAIR("Deployment", JSON_BUILD_STRING(c->data[PROP_DEPLOYMENT])),
JSON_BUILD_PAIR("Location", JSON_BUILD_STRING(c->data[PROP_LOCATION])),
JSON_BUILD_PAIR("KernelName", JSON_BUILD_STRING(u.sysname)),
JSON_BUILD_PAIR("KernelRelease", JSON_BUILD_STRING(u.release)),
JSON_BUILD_PAIR("KernelVersion", JSON_BUILD_STRING(u.version)),
JSON_BUILD_PAIR("OperatingSystemPrettyName", JSON_BUILD_STRING(c->data[PROP_OS_PRETTY_NAME])),
JSON_BUILD_PAIR("OperatingSystemCPEName", JSON_BUILD_STRING(c->data[PROP_OS_CPE_NAME])),
JSON_BUILD_PAIR("OperatingSystemHomeURL", JSON_BUILD_STRING(c->data[PROP_OS_HOME_URL])),
JSON_BUILD_PAIR("HardwareVendor", JSON_BUILD_STRING(vendor)),
JSON_BUILD_PAIR("HardwareModel", JSON_BUILD_STRING(model)),
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_ID128(product_uuid)),
JSON_BUILD_PAIR_CONDITION(sd_id128_is_null(product_uuid), "ProductUUID", JSON_BUILD_NULL)));
if (r < 0)
return log_error_errno(r, "Failed to build JSON data: %m");
r = json_variant_format(v, 0, &text);
if (r < 0)
return log_error_errno(r, "Failed to format JSON data: %m");
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0)
return r;
r = sd_bus_message_append(reply, "s", text);
if (r < 0)
return r;
@ -1059,6 +1181,11 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PARAM(uuid),
method_get_product_uuid,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("Describe",
SD_BUS_NO_ARGS,
SD_BUS_RESULT("s", json),
method_describe,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END,
};

View File

@ -210,3 +210,25 @@ sd_id128_t id128_make_v4_uuid(sd_id128_t id) {
}
DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func);
int id128_get_product(sd_id128_t *ret) {
sd_id128_t uuid;
int r;
assert(ret);
/* Reads the systems product UUID from DMI or devicetree (where it is located on POWER). This is
* particularly relevant in VM environments, where VM managers typically place a VM uuid there. */
r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
if (r == -ENOENT)
r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid);
if (r < 0)
return r;
if (sd_id128_is_null(uuid) || sd_id128_is_allf(uuid))
return -EADDRNOTAVAIL; /* Recognizable error */
*ret = uuid;
return 0;
}

View File

@ -36,3 +36,5 @@ int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_;
extern const struct hash_ops id128_hash_ops;
sd_id128_t id128_make_v4_uuid(sd_id128_t id);
int id128_get_product(sd_id128_t *ret);

View File

@ -1274,7 +1274,9 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
if (link->network->dhcp_send_release) {
r = sd_dhcp_client_send_release(client);
if (r < 0)
log_link_warning_errno(link, r, "Failed to send DHCP RELEASE, ignoring: %m");
log_link_full_errno(link,
ERRNO_IS_DISCONNECT(r) ? LOG_DEBUG : LOG_WARNING,
r, "Failed to send DHCP RELEASE, ignoring: %m");
}
r = dhcp_lease_lost(link);

View File

@ -2967,15 +2967,3 @@ static const char* const link_state_table[_LINK_STATE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full_errno(link, level, err,
"%s: %s%s%s%m",
msg,
strempty(err_msg),
err_msg && !endswith(err_msg, ".") ? "." : "",
err_msg ? " " : "");
}

View File

@ -237,10 +237,3 @@ int link_reconfigure(Link *link, bool force);
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
#define log_link_message_notice_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
#define log_link_message_info_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_INFO, err, msg)
#define log_link_message_debug_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)

View File

@ -87,8 +87,8 @@ struct Manager {
usec_t speed_meter_usec_new;
usec_t speed_meter_usec_old;
bool dhcp4_prefix_root_cannot_set_table:1;
bool bridge_mdb_on_master_not_supported:1;
bool dhcp4_prefix_root_cannot_set_table;
bool bridge_mdb_on_master_not_supported;
FirewallContext *fw_ctx;
};

View File

@ -645,7 +645,7 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
/* link may be NULL */
if (in_addr_is_set(route->gw_family, &route->gw)) {
if (in_addr_is_set(route->gw_family, &route->gw) && route->nexthop_id == 0) {
if (route->gw_family == route->family) {
r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->gw_family, &route->gw);
if (r < 0)
@ -717,10 +717,6 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
}
}
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
if (!route_type_is_reject(route) && route->nexthop_id == 0) {
assert(link); /* Those routes must be attached to a specific link */
@ -769,6 +765,7 @@ int route_remove(
link_netlink_message_handler_t callback) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
unsigned char type;
int r;
assert(link || manager);
@ -786,6 +783,21 @@ int route_remove(
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
if (route->family == AF_INET && route->nexthop_id > 0 && route->type == RTN_BLACKHOLE)
/* When IPv4 route has nexthop id and the nexthop type is blackhole, even though kernel
* sends RTM_NEWROUTE netlink message with blackhole type, kernel's internal route type
* fib_rt_info::type may not be blackhole. Thus, we cannot know the internal value.
* Moreover, on route removal, the matching is done with the hidden value if we set
* non-zero type in RTM_DELROUTE message. Note, sd_rtnl_message_new_route() sets
* RTN_UNICAST by default. So, we need to clear the type here. */
type = RTN_UNSPEC;
else
type = route->type;
r = sd_rtnl_message_route_set_type(req, type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
r = route_set_netlink_message(route, req, link);
if (r < 0)
return r;
@ -842,6 +854,9 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
routes = foreign ? manager->routes_foreign : manager->routes;
SET_FOREACH(route, routes) {
if (route->removing)
continue;
/* Do not touch routes managed by the kernel. */
if (route->protocol == RTPROT_KERNEL)
continue;
@ -855,6 +870,8 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
k = route_remove(route, manager, NULL, NULL);
if (k < 0 && r >= 0)
r = k;
route->removing = true;
}
return r;
@ -1083,8 +1100,8 @@ int route_configure(
Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r, k = 0;
Route *nr;
int r, k;
assert(link);
assert(link->manager);
@ -1106,6 +1123,10 @@ int route_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m");
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_link_error_errno(link, r, "Could not set route type: %m");
r = route_set_netlink_message(route, req, link);
if (r < 0)
return r;
@ -1167,19 +1188,22 @@ int route_configure(
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ordered_set_isempty(route->multipath_routes)) {
if (route->nexthop_id != 0 ||
in_addr_is_set(route->gw_family, &route->gw) ||
ordered_set_isempty(route->multipath_routes)) {
k = route_add_and_setup_timer(link, route, NULL, &nr);
if (k < 0)
return k;
} else {
MultipathRoute *m;
r = append_nexthops(route, req);
if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
assert(!ret);
k = 0;
ORDERED_SET_FOREACH(m, route->multipath_routes) {
r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0)
@ -2745,8 +2769,17 @@ static int route_section_verify(Route *route, Network *network) {
route->section->filename, route->section->line);
}
if ((route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->gw_family, &route->gw)) &&
!ordered_set_isempty(route->multipath_routes))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway= cannot be specified with MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
if (route->nexthop_id > 0 &&
(in_addr_is_set(route->gw_family, &route->gw) ||
(route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->gw_family, &route->gw) ||
!ordered_set_isempty(route->multipath_routes)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "

View File

@ -52,6 +52,7 @@ typedef struct Route {
bool protocol_set:1;
bool pref_set:1;
bool gateway_from_dhcp_or_ra:1;
bool removing:1;
union in_addr_union gw;
union in_addr_union dst;

View File

@ -2,6 +2,7 @@
#include "condition.h"
#include "conf-parser.h"
#include "networkd-link.h"
#include "networkd-util.h"
#include "parse-util.h"
#include "string-table.h"
@ -223,3 +224,17 @@ unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
return n + 1;
}
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg) {
const char *err_msg = NULL;
/* link may be NULL. */
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_link_full_errno(link, level, err,
"%s: %s%s%s%m",
msg,
strempty(err_msg),
err_msg && !endswith(err_msg, ".") ? "." : "",
err_msg ? " " : "");
}

View File

@ -11,6 +11,8 @@
#include "network-util.h"
#include "string-util.h"
typedef struct Link Link;
typedef struct NetworkConfigSection {
unsigned line;
bool invalid;
@ -73,9 +75,15 @@ static inline bool section_is_invalid(NetworkConfigSection *section) {
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);
static inline int log_message_warning_errno(sd_netlink_message *m, int err, const char *msg) {
const char *err_msg = NULL;
(void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg);
return log_warning_errno(err, "%s: %s%s%m", msg, strempty(err_msg), err_msg ? " " : "");
}
int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, int err, const char *msg);
#define log_link_message_error_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_ERR, err, msg)
#define log_link_message_warning_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_WARNING, err, msg)
#define log_link_message_notice_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_NOTICE, err, msg)
#define log_link_message_info_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_INFO, err, msg)
#define log_link_message_debug_errno(link, m, err, msg) log_link_message_full_errno(link, m, LOG_DEBUG, err, msg)
#define log_message_full_errno(m, level, err, msg) log_link_message_full_errno(NULL, m, level, err, msg)
#define log_message_error_errno(m, err, msg) log_message_full_errno(m, LOG_ERR, err, msg)
#define log_message_warning_errno(m, err, msg) log_message_full_errno(m, LOG_WARNING, err, msg)
#define log_message_notice_errno(m, err, msg) log_message_full_errno(m, LOG_NOTICE, err, msg)
#define log_message_info_errno(m, err, msg) log_message_full_errno(m, LOG_INFO, err, msg)
#define log_message_debug_errno(m, err, msg) log_message_full_errno(m, LOG_DEBUG, err, msg)

View File

@ -62,16 +62,10 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) {
} else if (detect_vm() == VIRTUALIZATION_KVM) {
/* If we are not running in a container, see if we are
* running in qemu/kvm and a machine ID was passed in
* via -uuid on the qemu/kvm command line */
/* If we are not running in a container, see if we are running in qemu/kvm and a
* machine ID was passed in via -uuid on the qemu/kvm command line */
if (id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, ret) >= 0) {
log_info("Initializing machine ID from KVM UUID.");
return 0;
}
/* on POWER, it's exported here instead */
if (id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, ret) >= 0) {
if (id128_get_product(ret) >= 0) {
log_info("Initializing machine ID from KVM UUID.");
return 0;
}

View File

@ -33,6 +33,7 @@ typedef enum NamingSchemeFlags {
NAMING_NSPAWN_LONG_HASH = 1 << 8, /* Shorten nspawn interfaces by including 24bit hash, instead of simple truncation */
NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */
NAMING_SLOT_FUNCTION_ID = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */
NAMING_16BIT_INDEX = 1 << 11, /* Allow full 16-bit for the onboard index */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
@ -42,7 +43,7 @@ typedef enum NamingSchemeFlags {
NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
NAMING_V245 = NAMING_V243 | NAMING_NSPAWN_LONG_HASH,
NAMING_V247 = NAMING_V245 | NAMING_BRIDGE_NO_SLOT,
NAMING_V249 = NAMING_V247 | NAMING_SLOT_FUNCTION_ID,
NAMING_V249 = NAMING_V247 | NAMING_SLOT_FUNCTION_ID | NAMING_16BIT_INDEX,
_NAMING_SCHEME_FLAGS_INVALID = -EINVAL,
} NamingSchemeFlags;

View File

@ -37,7 +37,8 @@
#include "strxcpyx.h"
#include "udev-builtin.h"
#define ONBOARD_INDEX_MAX (16*1024-1)
#define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
#define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
enum netname_type{
NET_UNDEF,
@ -162,6 +163,16 @@ static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn
return 0;
}
static bool is_valid_onboard_index(unsigned long idx) {
/* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
* report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
* pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
* interface a system might have. Ideally the kernel would already filter this crap for us, but it
* doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which
* allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */
return idx <= (naming_scheme_has(NAMING_16BIT_INDEX) ? ONBOARD_16BIT_INDEX_MAX : ONBOARD_14BIT_INDEX_MAX);
}
/* retrieve on-board index number and label from firmware */
static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
unsigned long idx, dev_port = 0;
@ -184,12 +195,7 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
return -EINVAL;
/* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
* report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
* pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
* interface a system might have. Ideally the kernel would already filter this crap for us, but it
* doesn't currently. */
if (idx > ONBOARD_INDEX_MAX)
if (!is_valid_onboard_index(idx))
return -ENOENT;
/* kernel provided port index for multiple ports on a single PCI function */

View File

@ -11,6 +11,8 @@
Description=Process Core Dump Socket
Documentation=man:systemd-coredump(8)
DefaultDependencies=no
Before=shutdown.target
Conflicts=shutdown.target
[Socket]
ListenSequentialPacket=/run/systemd/coredump