diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index 82bb52b344..07a65864bd 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -55,6 +55,10 @@ All tools: * `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`. +* `$SYSTEMD_DEFAULT_HOSTNAME` — override the compiled-in fallback hostname + (relevant in particular for the system manager and `systemd-hostnamed`). + Must be a valid hostname (either a single label or a FQDN). + * `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection method. Defaults to `auto`. Behavior is defined as follows: `auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index d7aba2c263..5109605e0c 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -3,14 +3,27 @@ #include #include #include +#include #include #include #include "alloc-util.h" #include "hostname-util.h" +#include "os-util.h" #include "string-util.h" #include "strv.h" +char* get_default_hostname(void) { + const char *e = secure_getenv("SYSTEMD_DEFAULT_HOSTNAME"); + if (e) { + if (hostname_is_valid(e, 0)) + return strdup(e); + log_debug("Invalid hostname in $SYSTEMD_DEFAULT_HOSTNAME, ignoring: %s", e); + } + + return strdup(FALLBACK_HOSTNAME); +} + char* gethostname_malloc(void) { struct utsname u; const char *s; @@ -23,7 +36,7 @@ char* gethostname_malloc(void) { s = u.nodename; if (isempty(s) || streq(s, "(none)")) - s = FALLBACK_HOSTNAME; + return get_default_hostname(); return strdup(s); } @@ -31,6 +44,7 @@ char* gethostname_malloc(void) { char* gethostname_short_malloc(void) { struct utsname u; const char *s; + _cleanup_free_ char *f = NULL; /* Like above, but kills the FQDN part if present. */ @@ -38,7 +52,10 @@ char* gethostname_short_malloc(void) { s = u.nodename; if (isempty(s) || streq(s, "(none)") || s[0] == '.') { - s = FALLBACK_HOSTNAME; + s = f = get_default_hostname(); + if (!s) + return NULL; + assert(s[0] != '.'); } diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h index 6cff9c1d4c..576ca083e0 100644 --- a/src/basic/hostname-util.h +++ b/src/basic/hostname-util.h @@ -7,6 +7,7 @@ #include "macro.h" #include "strv.h" +char* get_default_hostname(void); char* gethostname_malloc(void); char* gethostname_short_malloc(void); int gethostname_strict(char **ret); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index eb06957397..9937d159f4 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -322,6 +322,7 @@ static int context_update_kernel_hostname( Context *c, const char *transient_hn) { + _cleanup_free_ char *_hn_free = NULL; const char *hn; HostnameSource hns; int r; @@ -340,7 +341,10 @@ static int context_update_kernel_hostname( /* ... and the ultimate fallback */ } else { - hn = FALLBACK_HOSTNAME; + hn = _hn_free = get_default_hostname(); + if (!hn) + return log_oom(); + hns = HOSTNAME_FALLBACK; } @@ -502,16 +506,20 @@ static int property_get_hostname( void *userdata, sd_bus_error *error) { - _cleanup_free_ char *current = NULL; + _cleanup_free_ char *hn = NULL; int r; - r = gethostname_strict(¤t); - if (r == -ENXIO) - return sd_bus_message_append(reply, "s", FALLBACK_HOSTNAME); - if (r < 0) - return r; + r = gethostname_strict(&hn); + if (r < 0) { + if (r != -ENXIO) + return r; - return sd_bus_message_append(reply, "s", current); + hn = get_default_hostname(); + if (!hn) + return -ENOMEM; + } + + return sd_bus_message_append(reply, "s", hn); } static int property_get_static_hostname( @@ -531,7 +539,21 @@ static int property_get_static_hostname( return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]); } -static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME); +static int property_get_fallback_hostname( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *hn = get_default_hostname(); + if (!hn) + return log_oom(); + + return sd_bus_message_append(reply, "s", hn); +} static int property_get_hostname_source( sd_bus *bus, diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 2ed9f2d47b..ae46d2dcd8 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -442,20 +442,25 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char return 0; } -static const char *fallback_hostname(void) { +static char* fallback_hostname(void) { - /* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be - * "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */ + /* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it + * to be "localhost" even if that's the default hostname. In this case, let's revert to "linux" + * instead. */ - if (is_localhost(FALLBACK_HOSTNAME)) - return "linux"; + _cleanup_free_ char *n = get_default_hostname(); + if (!n) + return NULL; - return FALLBACK_HOSTNAME; + if (is_localhost(n)) + return strdup("linux"); + + return TAKE_PTR(n); } static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { - _cleanup_free_ char *n = NULL, *m = NULL; - char label[DNS_LABEL_MAX], *h; + _cleanup_free_ char *h = NULL, *n = NULL, *m = NULL; + char label[DNS_LABEL_MAX]; const char *p; int r; @@ -463,7 +468,10 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, assert(llmnr_hostname); assert(mdns_hostname); - p = fallback_hostname(); + p = h = fallback_hostname(); + if (!h) + return log_oom(); + r = dns_label_unescape(&p, label, sizeof label, 0); if (r < 0) return log_error_errno(r, "Failed to unescape fallback hostname: %m"); @@ -478,14 +486,9 @@ static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, if (r < 0) return log_error_errno(r, "Failed to concatenate mDNS hostname: %m"); - h = strdup(fallback_hostname()); - if (!h) - return log_oom(); - *llmnr_hostname = TAKE_PTR(n); *mdns_hostname = TAKE_PTR(m); - - *full_hostname = h; + *full_hostname = TAKE_PTR(h); return 0; } diff --git a/src/shared/hostname-setup.c b/src/shared/hostname-setup.c index 5cdcdbd93c..0cc1a268bd 100644 --- a/src/shared/hostname-setup.c +++ b/src/shared/hostname-setup.c @@ -194,7 +194,7 @@ int hostname_setup(bool really) { } } - if (isempty(hn)) { + if (!hn) { /* Don't override the hostname if it is already set and not explicitly configured */ char buf[HOST_NAME_MAX + 1] = {}; @@ -206,7 +206,10 @@ int hostname_setup(bool really) { if (enoent) log_info("No hostname configured, using fallback hostname."); - hn = FALLBACK_HOSTNAME; + hn = b = get_default_hostname(); + if (!hn) + return log_oom(); + source = HOSTNAME_FALLBACK; } diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c index 24c8ed9e3b..6d62958d67 100644 --- a/src/test/test-hostname-util.c +++ b/src/test/test-hostname-util.c @@ -10,6 +10,8 @@ #include "tmpfile-util.h" static void test_hostname_is_valid(void) { + log_info("/* %s */", __func__); + assert_se(hostname_is_valid("foobar", 0)); assert_se(hostname_is_valid("foobar.com", 0)); assert_se(!hostname_is_valid("foobar.com.", 0)); @@ -49,6 +51,8 @@ static void test_hostname_is_valid(void) { static void test_hostname_cleanup(void) { char *s; + log_info("/* %s */", __func__); + s = strdupa("foobar"); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa("foobar.com"); @@ -94,6 +98,8 @@ static void test_hostname_cleanup(void) { static void test_hostname_malloc(void) { _cleanup_free_ char *h = NULL, *l = NULL; + log_info("/* %s */", __func__); + assert_se(h = gethostname_malloc()); log_info("hostname_malloc: \"%s\"", h); @@ -101,21 +107,27 @@ static void test_hostname_malloc(void) { log_info("hostname_short_malloc: \"%s\"", l); } -static void test_fallback_hostname(void) { +static void test_default_hostname(void) { + log_info("/* %s */", __func__); + if (!hostname_is_valid(FALLBACK_HOSTNAME, 0)) { log_error("Configured fallback hostname \"%s\" is not valid.", FALLBACK_HOSTNAME); exit(EXIT_FAILURE); } + + _cleanup_free_ char *n = get_default_hostname(); + assert_se(n); + log_info("get_default_hostname: \"%s\"", n); + assert_se(hostname_is_valid(n, 0)); } int main(int argc, char *argv[]) { - test_setup_logging(LOG_INFO); + test_setup_logging(LOG_DEBUG); test_hostname_is_valid(); test_hostname_cleanup(); test_hostname_malloc(); - - test_fallback_hostname(); + test_default_hostname(); return 0; }