mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
hostnamed,shared/hostname-setup: expose the origin of the current hostname
In hostnamed this is exposed as a dbus property, and in the logs in both places. This is of interest to network management software and such: if the fallback hostname is used, it's not as useful as the real configured thing. Right now various programs try to guess the source of hostname by looking at the string. E.g. "localhost" is assumed to be not the real hostname, but "fedora" is. Any such attempts are bound to fail, because we cannot distinguish "fedora" (a fallback value set by a distro), from "fedora" (received from reverse dns), from "fedora" read from /etc/hostname. /run/systemd/fallback-hostname is written with the fallback hostname when either pid1 or hostnamed sets the kernel hostname to the fallback value. Why remember the fallback value and not the transient hostname in /run/hostname instead? We have three hostname types: "static", "transient", fallback". – Distinguishing "static" is easy: the hostname that is set matches what is in /etc/hostname. – Distingiushing "transient" and "fallback" is not easy. And the "transient" hostname may be set outside of pid1+hostnamed. In particular, it may be set by container manager, some non-systemd tool in the initramfs, or even by a direct call. All those mechanisms count as "transient". Trying to get those cases to write /run/hostname is futile. It is much easier to isolate the "fallback" case which is mostly under our control. And since the file is only used as a flag to mark the hostname as fallback, it can be hidden inside of our /run/systemd directory. For https://bugzilla.redhat.com/show_bug.cgi?id=1892235.
This commit is contained in:
parent
d39079fcaa
commit
60e4fb4240
@ -64,6 +64,7 @@ node /org/freedesktop/hostname1 {
|
|||||||
readonly s PrettyHostname = '...';
|
readonly s PrettyHostname = '...';
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly s FallbackHostname = '...';
|
readonly s FallbackHostname = '...';
|
||||||
|
readonly s HostnameSource = '...';
|
||||||
readonly s IconName = '...';
|
readonly s IconName = '...';
|
||||||
readonly s Chassis = '...';
|
readonly s Chassis = '...';
|
||||||
readonly s Deployment = '...';
|
readonly s Deployment = '...';
|
||||||
@ -117,6 +118,8 @@ node /org/freedesktop/hostname1 {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="FallbackHostname"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="FallbackHostname"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="HostnameSource"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="IconName"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="IconName"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="Chassis"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="Chassis"/>
|
||||||
@ -171,6 +174,11 @@ node /org/freedesktop/hostname1 {
|
|||||||
<para>The <varname>FallbackHostname</varname> property exposes the fallback hostname (configured at
|
<para>The <varname>FallbackHostname</varname> property exposes the fallback hostname (configured at
|
||||||
compilation time).</para>
|
compilation time).</para>
|
||||||
|
|
||||||
|
<para>The <varname>HostnameSource</varname> property exposes the origin of the currently configured
|
||||||
|
hostname. One of <literal>static</literal> (set from <filename>/etc/hostname</filename>),
|
||||||
|
<literal>transient</literal> (a non-permanent hostname from an external source),
|
||||||
|
<literal>fallback</literal> (the compiled-in fallback value).</para>
|
||||||
|
|
||||||
<para>The <varname>IconName</varname> property exposes the <emphasis>icon name</emphasis> following the
|
<para>The <varname>IconName</varname> property exposes the <emphasis>icon name</emphasis> following the
|
||||||
XDG icon naming spec. If not set, information such as the chassis type (see below) is used to find a
|
XDG icon naming spec. If not set, information such as the chassis type (see below) is used to find a
|
||||||
suitable fallback icon name (i.e. <literal>computer-laptop</literal>
|
suitable fallback icon name (i.e. <literal>computer-laptop</literal>
|
||||||
|
@ -78,6 +78,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
|
|||||||
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
|
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
|
||||||
|
|
||||||
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
|
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
|
||||||
|
#define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "service-util.h"
|
#include "service-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
|
#include "string-table.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -60,6 +61,8 @@ enum {
|
|||||||
typedef struct Context {
|
typedef struct Context {
|
||||||
char *data[_PROP_MAX];
|
char *data[_PROP_MAX];
|
||||||
|
|
||||||
|
HostnameSource hostname_source;
|
||||||
|
|
||||||
struct stat etc_hostname_stat;
|
struct stat etc_hostname_stat;
|
||||||
struct stat etc_os_release_stat;
|
struct stat etc_os_release_stat;
|
||||||
struct stat etc_machine_info_stat;
|
struct stat etc_machine_info_stat;
|
||||||
@ -317,35 +320,46 @@ static int context_update_kernel_hostname(
|
|||||||
const char *transient_hn) {
|
const char *transient_hn) {
|
||||||
|
|
||||||
const char *hn;
|
const char *hn;
|
||||||
struct utsname u;
|
HostnameSource hns;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
if (!transient_hn) {
|
|
||||||
/* If no transient hostname is passed in, then let's check what is currently set. */
|
|
||||||
assert_se(uname(&u) >= 0);
|
|
||||||
transient_hn =
|
|
||||||
isempty(u.nodename) || streq(u.nodename, "(none)") ? NULL : u.nodename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* /etc/hostname has the highest preference ... */
|
/* /etc/hostname has the highest preference ... */
|
||||||
if (c->data[PROP_STATIC_HOSTNAME])
|
if (c->data[PROP_STATIC_HOSTNAME]) {
|
||||||
hn = c->data[PROP_STATIC_HOSTNAME];
|
hn = c->data[PROP_STATIC_HOSTNAME];
|
||||||
|
hns = HOSTNAME_STATIC;
|
||||||
|
|
||||||
/* ... the transient hostname, (ie: DHCP) comes next ... */
|
/* ... the transient hostname, (ie: DHCP) comes next ... */
|
||||||
else if (!isempty(transient_hn))
|
} else if (transient_hn) {
|
||||||
hn = transient_hn;
|
hn = transient_hn;
|
||||||
|
hns = HOSTNAME_TRANSIENT;
|
||||||
|
|
||||||
/* ... and the ultimate fallback */
|
/* ... and the ultimate fallback */
|
||||||
else
|
} else {
|
||||||
hn = FALLBACK_HOSTNAME;
|
hn = FALLBACK_HOSTNAME;
|
||||||
|
hns = HOSTNAME_FALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
r = sethostname_idempotent(hn);
|
r = sethostname_idempotent(hn);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Failed to set hostname: %m");
|
||||||
|
|
||||||
|
if (c->hostname_source != hns) {
|
||||||
|
c->hostname_source = hns;
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
|
||||||
(void) nscd_flush_cache(STRV_MAKE("hosts"));
|
(void) nscd_flush_cache(STRV_MAKE("hosts"));
|
||||||
|
|
||||||
|
if (r == 0)
|
||||||
|
log_debug("Hostname was already set to <%s>.", hn);
|
||||||
|
else {
|
||||||
|
log_info("Hostname set to <%s> (%s)", hn, hostname_source_to_string(hns));
|
||||||
|
|
||||||
|
hostname_update_source_hint(hn, hns);
|
||||||
|
}
|
||||||
|
|
||||||
return r; /* 0 if no change, 1 if something was done */
|
return r; /* 0 if no change, 1 if something was done */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,6 +466,50 @@ static int property_get_static_hostname(
|
|||||||
|
|
||||||
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME);
|
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME);
|
||||||
|
|
||||||
|
static int property_get_hostname_source(
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *path,
|
||||||
|
const char *interface,
|
||||||
|
const char *property,
|
||||||
|
sd_bus_message *reply,
|
||||||
|
void *userdata,
|
||||||
|
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 fallback 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/fallback-hostname", &fallback);
|
||||||
|
if (r < 0 && r != -ENOENT)
|
||||||
|
log_warning_errno(r, "Failed to read /run/systemd/fallback-hostname, ignoring: %m");
|
||||||
|
|
||||||
|
if (streq_ptr(fallback, hostname))
|
||||||
|
c->hostname_source = HOSTNAME_FALLBACK;
|
||||||
|
else
|
||||||
|
c->hostname_source = HOSTNAME_TRANSIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
|
||||||
|
}
|
||||||
|
|
||||||
static int property_get_machine_info_field(
|
static int property_get_machine_info_field(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *path,
|
const char *path,
|
||||||
@ -570,7 +628,6 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
Context *c = userdata;
|
Context *c = userdata;
|
||||||
const char *name;
|
const char *name;
|
||||||
int interactive, r;
|
int interactive, r;
|
||||||
struct utsname u;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(c);
|
assert(c);
|
||||||
@ -579,20 +636,15 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
context_read_etc_hostname(c);
|
name = empty_to_null(name);
|
||||||
|
|
||||||
if (isempty(name))
|
/* We always go through with the procedure below without comparing to the current hostname, because
|
||||||
name = c->data[PROP_STATIC_HOSTNAME];
|
* we might want to adjust hostname source information even if the actual hostname is unchanged. */
|
||||||
|
|
||||||
if (isempty(name))
|
|
||||||
name = FALLBACK_HOSTNAME;
|
|
||||||
|
|
||||||
if (!hostname_is_valid(name, 0))
|
if (!hostname_is_valid(name, 0))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
||||||
|
|
||||||
assert_se(uname(&u) >= 0);
|
context_read_etc_hostname(c);
|
||||||
if (streq_ptr(name, u.nodename))
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
|
||||||
|
|
||||||
r = bus_verify_polkit_async(
|
r = bus_verify_polkit_async(
|
||||||
m,
|
m,
|
||||||
@ -609,18 +661,12 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||||
|
|
||||||
r = context_update_kernel_hostname(c, name);
|
r = context_update_kernel_hostname(c, name);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to set hostname: %m");
|
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
||||||
} else if (r == 0)
|
else if (r > 0)
|
||||||
log_debug("Hostname was already set to <%s>.", name);
|
|
||||||
else {
|
|
||||||
log_info("Hostname set to <%s>", name);
|
|
||||||
|
|
||||||
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
||||||
"/org/freedesktop/hostname1", "org.freedesktop.hostname1",
|
"/org/freedesktop/hostname1", "org.freedesktop.hostname1",
|
||||||
"Hostname", "HostnameSource", NULL);
|
"Hostname", "HostnameSource", NULL);
|
||||||
}
|
|
||||||
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
}
|
}
|
||||||
@ -645,7 +691,7 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
|||||||
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
|
|
||||||
if (!isempty(name) && !hostname_is_valid(name, 0))
|
if (name && !hostname_is_valid(name, 0))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
||||||
|
|
||||||
r = bus_verify_polkit_async(
|
r = bus_verify_polkit_async(
|
||||||
@ -666,25 +712,21 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = context_update_kernel_hostname(c, NULL);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to set hostname: %m");
|
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
r = context_write_data_static_hostname(c);
|
r = context_write_data_static_hostname(c);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to write static hostname: %m");
|
log_error_errno(r, "Failed to write static hostname: %m");
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->data[PROP_STATIC_HOSTNAME])
|
r = context_update_kernel_hostname(c, NULL);
|
||||||
log_info("Changed static hostname to <%s>", c->data[PROP_STATIC_HOSTNAME]);
|
if (r < 0) {
|
||||||
else
|
log_error_errno(r, "Failed to set hostname: %m");
|
||||||
log_info("Unset static hostname.");
|
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
||||||
|
}
|
||||||
|
|
||||||
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
||||||
"/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL);
|
"/org/freedesktop/hostname1", "org.freedesktop.hostname1",
|
||||||
|
"StaticHostname", "Hostname", "HostnameSource", NULL);
|
||||||
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
}
|
}
|
||||||
@ -850,6 +892,7 @@ static const sd_bus_vtable hostname_vtable[] = {
|
|||||||
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("FallbackHostname", "s", property_get_fallback_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("FallbackHostname", "s", property_get_fallback_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
@ -960,7 +1003,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(context_destroy) Context context = {};
|
_cleanup_(context_destroy) Context context = {
|
||||||
|
.hostname_source = _HOSTNAME_INVALID, /* appropriate value will be set later */
|
||||||
|
};
|
||||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
@ -9,11 +9,13 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "fs-util.h"
|
||||||
#include "hostname-setup.h"
|
#include "hostname-setup.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "proc-cmdline.h"
|
#include "proc-cmdline.h"
|
||||||
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -39,6 +41,26 @@ int sethostname_idempotent(const char *s) {
|
|||||||
return sethostname_idempotent_full(s, true);
|
return sethostname_idempotent_full(s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]) {
|
||||||
|
char buf[HOST_NAME_MAX + 1] = {};
|
||||||
|
|
||||||
|
/* Returns true if we got a good hostname, false otherwise. */
|
||||||
|
|
||||||
|
if (gethostname(buf, sizeof(buf) - 1) < 0)
|
||||||
|
return false; /* This can realistically only fail with ENAMETOOLONG.
|
||||||
|
* Let's treat that case the same as an invalid hostname. */
|
||||||
|
|
||||||
|
if (isempty(buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* This is the built-in kernel default hostname */
|
||||||
|
if (streq(buf, "(none)"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memcpy(ret, buf, sizeof buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int shorten_overlong(const char *s, char **ret) {
|
int shorten_overlong(const char *s, char **ret) {
|
||||||
char *h, *p;
|
char *h, *p;
|
||||||
|
|
||||||
@ -123,24 +145,26 @@ int read_etc_hostname(const char *path, char **ret) {
|
|||||||
return read_etc_hostname_stream(f, ret);
|
return read_etc_hostname_stream(f, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hostname_is_set(void) {
|
void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||||
struct utsname u;
|
int r;
|
||||||
|
|
||||||
assert_se(uname(&u) >= 0);
|
/* Why save the value and not just create a flag file? This way we will
|
||||||
|
* notice if somebody sets the hostname directly (not going through hostnamed).
|
||||||
|
*/
|
||||||
|
|
||||||
if (isempty(u.nodename))
|
if (source == HOSTNAME_FALLBACK) {
|
||||||
return false;
|
r = write_string_file("/run/systemd/fallback-hostname", hostname,
|
||||||
|
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
|
||||||
/* This is the built-in kernel default hostname */
|
if (r < 0)
|
||||||
if (streq(u.nodename, "(none)"))
|
log_warning_errno(r, "Failed to create \"/run/systemd/fallback-hostname\": %m");
|
||||||
return false;
|
} else
|
||||||
|
unlink_or_warn("/run/systemd/fallback-hostname");
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hostname_setup(bool really) {
|
int hostname_setup(bool really) {
|
||||||
_cleanup_free_ char *b = NULL;
|
_cleanup_free_ char *b = NULL;
|
||||||
const char *hn = NULL;
|
const char *hn = NULL;
|
||||||
|
HostnameSource source;
|
||||||
bool enoent = false;
|
bool enoent = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -148,9 +172,10 @@ int hostname_setup(bool really) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
|
log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
|
||||||
else if (r > 0) {
|
else if (r > 0) {
|
||||||
if (hostname_is_valid(b, true))
|
if (hostname_is_valid(b, true)) {
|
||||||
hn = b;
|
hn = b;
|
||||||
else {
|
source = HOSTNAME_TRANSIENT;
|
||||||
|
} else {
|
||||||
log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
|
log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
|
||||||
b = mfree(b);
|
b = mfree(b);
|
||||||
}
|
}
|
||||||
@ -163,19 +188,27 @@ int hostname_setup(bool really) {
|
|||||||
enoent = true;
|
enoent = true;
|
||||||
else
|
else
|
||||||
log_warning_errno(r, "Failed to read configured hostname: %m");
|
log_warning_errno(r, "Failed to read configured hostname: %m");
|
||||||
} else
|
} else {
|
||||||
hn = b;
|
hn = b;
|
||||||
|
source = HOSTNAME_STATIC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isempty(hn)) {
|
if (isempty(hn)) {
|
||||||
/* Don't override the hostname if it is already set and not explicitly configured */
|
/* Don't override the hostname if it is already set and not explicitly configured */
|
||||||
if (hostname_is_set())
|
|
||||||
|
char buf[HOST_NAME_MAX + 1] = {};
|
||||||
|
if (get_hostname_filtered(buf)) {
|
||||||
|
log_debug("No hostname configured, leaving existing hostname <%s> in place.", buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (enoent)
|
if (enoent)
|
||||||
log_info("No hostname configured.");
|
log_info("No hostname configured, using fallback hostname.");
|
||||||
|
|
||||||
hn = FALLBACK_HOSTNAME;
|
hn = FALLBACK_HOSTNAME;
|
||||||
|
source = HOSTNAME_FALLBACK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sethostname_idempotent_full(hn, really);
|
r = sethostname_idempotent_full(hn, really);
|
||||||
@ -188,5 +221,16 @@ int hostname_setup(bool really) {
|
|||||||
really ? "set" : "would have been set",
|
really ? "set" : "would have been set",
|
||||||
hn);
|
hn);
|
||||||
|
|
||||||
|
if (really)
|
||||||
|
hostname_update_source_hint(hn, source);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* const hostname_source_table[] = {
|
||||||
|
[HOSTNAME_STATIC] = "static",
|
||||||
|
[HOSTNAME_TRANSIENT] = "transient",
|
||||||
|
[HOSTNAME_FALLBACK] = "fallback",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(hostname_source, HostnameSource);
|
||||||
|
@ -4,6 +4,14 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef enum HostnameSource {
|
||||||
|
HOSTNAME_STATIC, /* from /etc/hostname */
|
||||||
|
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
|
||||||
|
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
|
||||||
|
_HOSTNAME_INVALID = -1,
|
||||||
|
} HostnameSource;
|
||||||
|
|
||||||
|
const char* hostname_source_to_string(HostnameSource source);
|
||||||
int sethostname_idempotent(const char *s);
|
int sethostname_idempotent(const char *s);
|
||||||
|
|
||||||
int shorten_overlong(const char *s, char **ret);
|
int shorten_overlong(const char *s, char **ret);
|
||||||
@ -11,4 +19,6 @@ int shorten_overlong(const char *s, char **ret);
|
|||||||
int read_etc_hostname_stream(FILE *f, char **ret);
|
int read_etc_hostname_stream(FILE *f, char **ret);
|
||||||
int read_etc_hostname(const char *path, char **ret);
|
int read_etc_hostname(const char *path, char **ret);
|
||||||
|
|
||||||
|
bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]);
|
||||||
|
void hostname_update_source_hint(const char *hostname, HostnameSource source);
|
||||||
int hostname_setup(bool really);
|
int hostname_setup(bool really);
|
||||||
|
@ -32,7 +32,7 @@ ProtectKernelLogs=yes
|
|||||||
ProtectKernelModules=yes
|
ProtectKernelModules=yes
|
||||||
ProtectKernelTunables=yes
|
ProtectKernelTunables=yes
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ReadWritePaths=/etc
|
ReadWritePaths=/etc /run/systemd
|
||||||
RestrictAddressFamilies=AF_UNIX
|
RestrictAddressFamilies=AF_UNIX
|
||||||
RestrictNamespaces=yes
|
RestrictNamespaces=yes
|
||||||
RestrictRealtime=yes
|
RestrictRealtime=yes
|
||||||
|
Loading…
Reference in New Issue
Block a user