mirror of
https://github.com/systemd/systemd.git
synced 2025-03-22 06:50:18 +03:00
resolve question marks in /etc/hostname to characters hashed from machine ID (#36647)
So I have a bunch of particle os instances around, that I frequently factory reset. and it's confusing, since they all have the same name. Let's do something about this, and extend the hostname setup logic a bit to deal better with "cattle" rather than "pet" deployments. Specifically: if a hostname in /etc/hostname contains a bunch of question marks we'll replace it with hex chars hashed from the machine id. This allows us to do something like this: hostnamectl set-hostname --static 'funky-????-????-???' and we'll end up with a hostname like `funky-baf4-b653-e230`
This commit is contained in:
commit
ced634a62d
2
TODO
2
TODO
@ -1454,8 +1454,6 @@ Features:
|
||||
comes from, but we can still derive that from the stdin socket its output
|
||||
came from. We apparently don't do that right now.
|
||||
|
||||
* add ability to set hostname with suffix derived from machine id at boot
|
||||
|
||||
* add PR_SET_DUMPABLE service setting
|
||||
|
||||
* homed/userdb: maybe define a "companion" dir for home directories where apps
|
||||
|
@ -43,6 +43,13 @@
|
||||
attempt to make the name valid, but obviously it is recommended to use a valid name and not rely on this
|
||||
filtering.</para>
|
||||
|
||||
<para id="question-mark-hostname-pattern">If the question mark character <literal>?</literal> appears in
|
||||
the hostname, it is automatically substituted by a hexadecimal character derived from the
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> when
|
||||
applied, securely and deterministically by cryptographic hashing. Example:
|
||||
<literal>foobar-????-????</literal> will automatically expand to <literal>foobar-92a9-061c</literal> or
|
||||
similar, depending on the local machine ID.</para>
|
||||
|
||||
<para>You may use
|
||||
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to change
|
||||
the value of this file during runtime from the command line. Use
|
||||
|
@ -88,6 +88,8 @@
|
||||
name labels), or a sequence of such labels separated by single dots that forms a valid DNS FQDN. The
|
||||
hostname must be at most 64 characters, which is a Linux limitation (DNS allows longer names).</para>
|
||||
|
||||
<xi:include href="hostname.xml" xpointer="question-mark-hostname-pattern"/>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v249"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -538,6 +538,8 @@
|
||||
that forms a valid DNS FQDN. The hostname must be at most 64 characters, which is a Linux
|
||||
limitation (DNS allows longer names).</para>
|
||||
|
||||
<xi:include href="hostname.xml" xpointer="question-mark-hostname-pattern"/>
|
||||
|
||||
<para>See <citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for a description of how
|
||||
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
|
@ -14,13 +14,16 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
char* get_default_hostname(void) {
|
||||
char* get_default_hostname_raw(void) {
|
||||
int r;
|
||||
|
||||
/* Returns the default hostname, and leaves any ??? in place. */
|
||||
|
||||
const char *e = secure_getenv("SYSTEMD_DEFAULT_HOSTNAME");
|
||||
if (e) {
|
||||
if (hostname_is_valid(e, 0))
|
||||
if (hostname_is_valid(e, VALID_HOSTNAME_QUESTION_MARK))
|
||||
return strdup(e);
|
||||
|
||||
log_debug("Invalid hostname in $SYSTEMD_DEFAULT_HOSTNAME, ignoring: %s", e);
|
||||
}
|
||||
|
||||
@ -29,49 +32,15 @@ char* get_default_hostname(void) {
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse os-release, ignoring: %m");
|
||||
else if (f) {
|
||||
if (hostname_is_valid(f, 0))
|
||||
if (hostname_is_valid(f, VALID_HOSTNAME_QUESTION_MARK))
|
||||
return TAKE_PTR(f);
|
||||
|
||||
log_debug("Invalid hostname in os-release, ignoring: %s", f);
|
||||
}
|
||||
|
||||
return strdup(FALLBACK_HOSTNAME);
|
||||
}
|
||||
|
||||
int gethostname_full(GetHostnameFlags flags, char **ret) {
|
||||
_cleanup_free_ char *buf = NULL, *fallback = NULL;
|
||||
struct utsname u;
|
||||
const char *s;
|
||||
|
||||
assert(ret);
|
||||
|
||||
assert_se(uname(&u) >= 0);
|
||||
|
||||
s = u.nodename;
|
||||
if (isempty(s) || streq(s, "(none)") ||
|
||||
(!FLAGS_SET(flags, GET_HOSTNAME_ALLOW_LOCALHOST) && is_localhost(s)) ||
|
||||
(FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')) {
|
||||
if (!FLAGS_SET(flags, GET_HOSTNAME_FALLBACK_DEFAULT))
|
||||
return -ENXIO;
|
||||
|
||||
s = fallback = get_default_hostname();
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
if (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, GET_HOSTNAME_SHORT))
|
||||
buf = strdupcspn(s, ".");
|
||||
else
|
||||
buf = strdup(s);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool valid_ldh_char(char c) {
|
||||
/* "LDH" → "Letters, digits, hyphens", as per RFC 5890, Section 2.3.1 */
|
||||
|
||||
@ -116,7 +85,7 @@ bool hostname_is_valid(const char *s, ValidHostnameFlags flags) {
|
||||
hyphen = true;
|
||||
|
||||
} else {
|
||||
if (!valid_ldh_char(*p))
|
||||
if (!valid_ldh_char(*p) && (*p != '?' || !FLAGS_SET(flags, VALID_HOSTNAME_QUESTION_MARK)))
|
||||
return false;
|
||||
|
||||
dot = false;
|
||||
@ -158,7 +127,7 @@ char* hostname_cleanup(char *s) {
|
||||
dot = false;
|
||||
hyphen = true;
|
||||
|
||||
} else if (valid_ldh_char(*p)) {
|
||||
} else if (valid_ldh_char(*p) || *p == '?') {
|
||||
*(d++) = *p;
|
||||
dot = false;
|
||||
hyphen = false;
|
||||
|
@ -7,42 +7,14 @@
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
|
||||
typedef enum GetHostnameFlags {
|
||||
GET_HOSTNAME_ALLOW_LOCALHOST = 1 << 0, /* accepts "localhost" or friends. */
|
||||
GET_HOSTNAME_FALLBACK_DEFAULT = 1 << 1, /* use default hostname if no hostname is set. */
|
||||
GET_HOSTNAME_SHORT = 1 << 2, /* kills the FQDN part if present. */
|
||||
} GetHostnameFlags;
|
||||
|
||||
int gethostname_full(GetHostnameFlags flags, char **ret);
|
||||
static inline int gethostname_strict(char **ret) {
|
||||
return gethostname_full(0, ret);
|
||||
}
|
||||
|
||||
static inline char* gethostname_malloc(void) {
|
||||
char *s;
|
||||
|
||||
if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT, &s) < 0)
|
||||
return NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline char* gethostname_short_malloc(void) {
|
||||
char *s;
|
||||
|
||||
if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT | GET_HOSTNAME_SHORT, &s) < 0)
|
||||
return NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char* get_default_hostname(void);
|
||||
char* get_default_hostname_raw(void);
|
||||
|
||||
bool valid_ldh_char(char c) _const_;
|
||||
|
||||
typedef enum ValidHostnameFlags {
|
||||
VALID_HOSTNAME_TRAILING_DOT = 1 << 0, /* Accept trailing dot on multi-label names */
|
||||
VALID_HOSTNAME_DOT_HOST = 1 << 1, /* Accept ".host" as valid hostname */
|
||||
VALID_HOSTNAME_TRAILING_DOT = 1 << 0, /* Accept trailing dot on multi-label names */
|
||||
VALID_HOSTNAME_DOT_HOST = 1 << 1, /* Accept ".host" as valid hostname */
|
||||
VALID_HOSTNAME_QUESTION_MARK = 1 << 2, /* Accept "?" as place holder for hashed machine ID value */
|
||||
} ValidHostnameFlags;
|
||||
|
||||
bool hostname_is_valid(const char *s, ValidHostnameFlags flags) _pure_;
|
||||
|
@ -2453,12 +2453,11 @@ static int initialize_runtime(
|
||||
(void) import_credentials();
|
||||
|
||||
(void) os_release_status();
|
||||
(void) hostname_setup(/* really = */ true);
|
||||
(void) machine_id_setup(/* root = */ NULL, arg_machine_id,
|
||||
(first_boot ? MACHINE_ID_SETUP_FORCE_TRANSIENT : 0) |
|
||||
(arg_machine_id_from_firmware ? MACHINE_ID_SETUP_FORCE_FIRMWARE : 0),
|
||||
/* ret_machine_id = */ NULL);
|
||||
|
||||
(void) hostname_setup(/* really = */ true);
|
||||
(void) loopback_setup();
|
||||
|
||||
bump_unix_max_dgram_qlen();
|
||||
|
@ -1460,7 +1460,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_HOSTNAME:
|
||||
if (!hostname_is_valid(optarg, VALID_HOSTNAME_TRAILING_DOT))
|
||||
if (!hostname_is_valid(optarg, VALID_HOSTNAME_TRAILING_DOT|VALID_HOSTNAME_QUESTION_MARK))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Host name %s is not valid.", optarg);
|
||||
|
||||
|
@ -14,7 +14,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
fuzz_setup_logging();
|
||||
|
||||
(void) read_etc_hostname_stream(f, &ret);
|
||||
(void) read_etc_hostname_stream(f, /* substitute_wildcards= */ true, &ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ static int set_hostname(int argc, char **argv, void *userdata) {
|
||||
/* If the passed hostname is already valid, then assume the user doesn't know anything about pretty
|
||||
* hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic
|
||||
* hostname. */
|
||||
if (implicit && hostname_is_valid(hostname, VALID_HOSTNAME_TRAILING_DOT))
|
||||
if (implicit && hostname_is_valid(hostname, VALID_HOSTNAME_TRAILING_DOT|VALID_HOSTNAME_QUESTION_MARK))
|
||||
p = ""; /* No pretty hostname (as it is redundant), just a static one */
|
||||
else
|
||||
p = hostname; /* Use the passed name as pretty hostname */
|
||||
|
@ -52,6 +52,7 @@
|
||||
typedef enum {
|
||||
/* Read from /etc/hostname */
|
||||
PROP_STATIC_HOSTNAME,
|
||||
PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS,
|
||||
|
||||
/* Read from /etc/machine-info */
|
||||
PROP_PRETTY_HOSTNAME,
|
||||
@ -125,11 +126,25 @@ static void context_read_etc_hostname(Context *c) {
|
||||
stat_inode_unmodified(&c->etc_hostname_stat, ¤t_stat))
|
||||
return;
|
||||
|
||||
context_reset(c, UINT64_C(1) << PROP_STATIC_HOSTNAME);
|
||||
context_reset(c,
|
||||
(UINT64_C(1) << PROP_STATIC_HOSTNAME) |
|
||||
(UINT64_C(1) << PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS));
|
||||
|
||||
r = read_etc_hostname(NULL, &c->data[PROP_STATIC_HOSTNAME]);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read /etc/hostname, ignoring: %m");
|
||||
r = read_etc_hostname(/* path= */ NULL, /* substitute_wildcards= */ false, &c->data[PROP_STATIC_HOSTNAME]);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read /etc/hostname, ignoring: %m");
|
||||
} else {
|
||||
_cleanup_free_ char *substituted = strdup(c->data[PROP_STATIC_HOSTNAME]);
|
||||
if (!substituted)
|
||||
return (void) log_oom();
|
||||
|
||||
r = hostname_substitute_wildcards(substituted);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to substitute wildcards in /etc/hostname, ignoring: %m");
|
||||
else
|
||||
c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS] = TAKE_PTR(substituted);
|
||||
}
|
||||
|
||||
c->etc_hostname_stat = current_stat;
|
||||
}
|
||||
@ -678,8 +693,8 @@ static int context_update_kernel_hostname(
|
||||
assert(c);
|
||||
|
||||
/* /etc/hostname has the highest preference ... */
|
||||
if (c->data[PROP_STATIC_HOSTNAME]) {
|
||||
hn = c->data[PROP_STATIC_HOSTNAME];
|
||||
if (c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]) {
|
||||
hn = c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS];
|
||||
hns = HOSTNAME_STATIC;
|
||||
|
||||
/* ... the transient hostname, (ie: DHCP) comes next ... */
|
||||
@ -946,7 +961,7 @@ static int property_get_static_hostname(
|
||||
|
||||
context_read_etc_hostname(c);
|
||||
|
||||
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
|
||||
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]);
|
||||
}
|
||||
|
||||
static int property_get_default_hostname(
|
||||
@ -978,7 +993,7 @@ static void context_determine_hostname_source(Context *c) {
|
||||
|
||||
(void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hostname);
|
||||
|
||||
if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
|
||||
if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]))
|
||||
c->hostname_source = HOSTNAME_STATIC;
|
||||
else {
|
||||
_cleanup_free_ char *fallback = NULL;
|
||||
@ -1201,6 +1216,31 @@ static int property_get_vsock_cid(
|
||||
return sd_bus_message_append(reply, "u", (uint32_t) local_cid);
|
||||
}
|
||||
|
||||
static int validate_and_substitute_hostname(const char *name, char **ret_substituted, sd_bus_error *error) {
|
||||
int r;
|
||||
|
||||
assert(ret_substituted);
|
||||
|
||||
if (!name) {
|
||||
*ret_substituted = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *substituted = strdup(name);
|
||||
if (!substituted)
|
||||
return log_oom();
|
||||
|
||||
r = hostname_substitute_wildcards(substituted);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to substitute wildcards in hotname: %m");
|
||||
|
||||
if (!hostname_is_valid(substituted, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
||||
|
||||
*ret_substituted = TAKE_PTR(substituted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
Context *c = ASSERT_PTR(userdata);
|
||||
const char *name;
|
||||
@ -1217,10 +1257,12 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
||||
/* We always go through with the procedure below without comparing to the current hostname, because
|
||||
* we might want to adjust hostname source information even if the actual hostname is unchanged. */
|
||||
|
||||
if (name && !hostname_is_valid(name, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
||||
_cleanup_free_ char *substituted = NULL;
|
||||
r = validate_and_substitute_hostname(name, &substituted, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
context_read_etc_hostname(c);
|
||||
name = substituted;
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
m,
|
||||
@ -1235,6 +1277,8 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
context_read_etc_hostname(c);
|
||||
|
||||
r = context_update_kernel_hostname(c, name);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
||||
@ -1249,8 +1293,7 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
||||
static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
Context *c = ASSERT_PTR(userdata);
|
||||
const char *name;
|
||||
int interactive;
|
||||
int r;
|
||||
int interactive, r;
|
||||
|
||||
assert(m);
|
||||
|
||||
@ -1265,8 +1308,10 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
||||
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
||||
return sd_bus_reply_method_return(m, NULL);
|
||||
|
||||
if (name && !hostname_is_valid(name, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
||||
_cleanup_free_ char *substituted = NULL;
|
||||
r = validate_and_substitute_hostname(name, &substituted, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
m,
|
||||
@ -1285,6 +1330,8 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free_and_replace(c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS], substituted);
|
||||
|
||||
r = context_write_data_static_hostname(c);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to write static hostname: %m");
|
||||
@ -1295,7 +1342,7 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
|
||||
}
|
||||
|
||||
r = context_update_kernel_hostname(c, NULL);
|
||||
r = context_update_kernel_hostname(c, /* transient_hostname= */ 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");
|
||||
@ -1505,20 +1552,14 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
|
||||
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();
|
||||
|
||||
r = gethostname_strict(&hn);
|
||||
if (r < 0 && r != -ENXIO)
|
||||
return log_error_errno(r, "Failed to read local host name: %m");
|
||||
|
||||
if (isempty(c->data[PROP_ICON_NAME]))
|
||||
in = context_fallback_icon_name(c);
|
||||
|
||||
@ -1559,8 +1600,8 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
|
||||
|
||||
r = sd_json_buildo(
|
||||
&v,
|
||||
SD_JSON_BUILD_PAIR_STRING("Hostname", hn),
|
||||
SD_JSON_BUILD_PAIR_STRING("StaticHostname", c->data[PROP_STATIC_HOSTNAME]),
|
||||
SD_JSON_BUILD_PAIR_STRING("Hostname", hn ?: dhn),
|
||||
SD_JSON_BUILD_PAIR_STRING("StaticHostname", c->data[PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS]),
|
||||
SD_JSON_BUILD_PAIR_STRING("PrettyHostname", c->data[PROP_PRETTY_HOSTNAME]),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultHostname", dhn),
|
||||
SD_JSON_BUILD_PAIR_STRING("HostnameSource", hostname_source_to_string(c->hostname_source)),
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "glob-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "journal-internal.h"
|
||||
#include "journal-remote.h"
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "fsprg.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "io-util.h"
|
||||
#include "journal-authenticate.h"
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "initrd-util.h"
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "network-common.h"
|
||||
#include "random-util.h"
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "local-addresses.h"
|
||||
#include "macro.h"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "idn-util.h"
|
||||
#include "io-util.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "dns-def.h"
|
||||
#include "dns-domain.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "idn-util.h"
|
||||
#include "resolved-util.h"
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "main-func.h"
|
||||
#include "osc-context.h"
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "glob-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "ima-util.h"
|
||||
#include "id128-util.h"
|
||||
|
@ -1654,7 +1654,7 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name);
|
||||
else if (r >= 0) {
|
||||
r = read_etc_hostname(path, &hostname);
|
||||
r = read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read /etc/hostname of image %s: %m", i->name);
|
||||
}
|
||||
|
@ -3692,7 +3692,7 @@ int dissected_image_acquire_metadata(
|
||||
switch (k) {
|
||||
|
||||
case META_HOSTNAME:
|
||||
r = read_etc_hostname_stream(f, &hostname);
|
||||
r = read_etc_hostname_stream(f, /* substitute_wildcards= */ false, &hostname);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read /etc/hostname of image: %m");
|
||||
|
||||
|
@ -13,12 +13,14 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "initrd-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "siphash24.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
||||
@ -95,7 +97,7 @@ static int acquire_hostname_from_credential(char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_etc_hostname_stream(FILE *f, char **ret) {
|
||||
int read_etc_hostname_stream(FILE *f, bool substitute_wildcards, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
@ -114,9 +116,19 @@ int read_etc_hostname_stream(FILE *f, char **ret) {
|
||||
if (IN_SET(line[0], '\0', '#'))
|
||||
continue;
|
||||
|
||||
if (substitute_wildcards) {
|
||||
r = hostname_substitute_wildcards(line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
hostname_cleanup(line); /* normalize the hostname */
|
||||
|
||||
if (!hostname_is_valid(line, VALID_HOSTNAME_TRAILING_DOT)) /* check that the hostname we return is valid */
|
||||
/* check that the hostname we return is valid */
|
||||
if (!hostname_is_valid(
|
||||
line,
|
||||
VALID_HOSTNAME_TRAILING_DOT|
|
||||
(substitute_wildcards ? 0 : VALID_HOSTNAME_QUESTION_MARK)))
|
||||
return -EBADMSG;
|
||||
|
||||
*ret = TAKE_PTR(line);
|
||||
@ -124,7 +136,7 @@ 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, bool substitute_wildcards, char **ret) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
assert(ret);
|
||||
@ -136,12 +148,14 @@ int read_etc_hostname(const char *path, char **ret) {
|
||||
if (!f)
|
||||
return -errno;
|
||||
|
||||
return read_etc_hostname_stream(f, ret);
|
||||
return read_etc_hostname_stream(f, substitute_wildcards, ret);
|
||||
}
|
||||
|
||||
void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||
int r;
|
||||
|
||||
assert(hostname);
|
||||
|
||||
/* 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).
|
||||
*/
|
||||
@ -152,7 +166,7 @@ void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\", ignoring: %m");
|
||||
} else
|
||||
unlink_or_warn("/run/systemd/default-hostname");
|
||||
(void) unlink_or_warn("/run/systemd/default-hostname");
|
||||
}
|
||||
|
||||
int hostname_setup(bool really) {
|
||||
@ -174,7 +188,7 @@ int hostname_setup(bool really) {
|
||||
}
|
||||
|
||||
if (!hn) {
|
||||
r = read_etc_hostname(NULL, &hn);
|
||||
r = read_etc_hostname(/* path= */ NULL, /* substitute_wildcards= */ true, &hn);
|
||||
if (r == -ENOENT)
|
||||
enoent = true;
|
||||
else if (r < 0)
|
||||
@ -237,3 +251,99 @@ static const char* const hostname_source_table[] = {
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);
|
||||
|
||||
int hostname_substitute_wildcards(char *name) {
|
||||
static const sd_id128_t key = SD_ID128_MAKE(98,10,ad,df,8d,7d,4f,b5,89,1b,4b,56,ac,c2,26,8f);
|
||||
sd_id128_t mid = SD_ID128_NULL;
|
||||
size_t left_bits = 0, counter = 0;
|
||||
uint64_t h = 0;
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
|
||||
/* Replaces every occurrence of '?' in the specified string with a nibble hashed from
|
||||
* /etc/machine-id. This is supposed to be used on /etc/hostname files that want to automatically
|
||||
* configure a hostname derived from the machine ID in some form.
|
||||
*
|
||||
* Note that this does not directly use the machine ID, because that's not necessarily supposed to be
|
||||
* public information to be broadcast on the network, while the hostname certainly is. */
|
||||
|
||||
for (char *n = name; *n; n++) {
|
||||
if (*n != '?')
|
||||
continue;
|
||||
|
||||
if (left_bits <= 0) {
|
||||
if (sd_id128_is_null(mid)) {
|
||||
r = sd_id128_get_machine(&mid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
struct siphash state;
|
||||
siphash24_init(&state, key.bytes);
|
||||
siphash24_compress(&mid, sizeof(mid), &state);
|
||||
siphash24_compress(&counter, sizeof(counter), &state); /* counter mode */
|
||||
h = siphash24_finalize(&state);
|
||||
left_bits = sizeof(h) * 8;
|
||||
counter++;
|
||||
}
|
||||
|
||||
assert(left_bits >= 4);
|
||||
*n = hexchar(h & 0xf);
|
||||
h >>= 4;
|
||||
left_bits -= 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* get_default_hostname(void) {
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *h = get_default_hostname_raw();
|
||||
if (!h)
|
||||
return NULL;
|
||||
|
||||
r = hostname_substitute_wildcards(h);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to substitute wildcards in hostname, falling back to built-in name: %m");
|
||||
return strdup(FALLBACK_HOSTNAME);
|
||||
}
|
||||
|
||||
return TAKE_PTR(h);
|
||||
}
|
||||
|
||||
int gethostname_full(GetHostnameFlags flags, char **ret) {
|
||||
_cleanup_free_ char *buf = NULL, *fallback = NULL;
|
||||
struct utsname u;
|
||||
const char *s;
|
||||
|
||||
assert(ret);
|
||||
|
||||
assert_se(uname(&u) >= 0);
|
||||
|
||||
s = u.nodename;
|
||||
if (isempty(s) || streq(s, "(none)") ||
|
||||
(!FLAGS_SET(flags, GET_HOSTNAME_ALLOW_LOCALHOST) && is_localhost(s)) ||
|
||||
(FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')) {
|
||||
if (!FLAGS_SET(flags, GET_HOSTNAME_FALLBACK_DEFAULT))
|
||||
return -ENXIO;
|
||||
|
||||
s = fallback = get_default_hostname();
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
if (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, GET_HOSTNAME_SHORT))
|
||||
buf = strdupcspn(s, ".");
|
||||
else
|
||||
buf = strdup(s);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(buf);
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,8 +18,42 @@ int sethostname_idempotent(const char *s);
|
||||
|
||||
int shorten_overlong(const char *s, char **ret);
|
||||
|
||||
int read_etc_hostname_stream(FILE *f, char **ret);
|
||||
int read_etc_hostname(const char *path, char **ret);
|
||||
int read_etc_hostname_stream(FILE *f, bool substitute_wildcards, char **ret);
|
||||
int read_etc_hostname(const char *path, bool substitue_wildcards, char **ret);
|
||||
|
||||
void hostname_update_source_hint(const char *hostname, HostnameSource source);
|
||||
int hostname_setup(bool really);
|
||||
|
||||
int hostname_substitute_wildcards(char *name);
|
||||
|
||||
char* get_default_hostname(void);
|
||||
|
||||
typedef enum GetHostnameFlags {
|
||||
GET_HOSTNAME_ALLOW_LOCALHOST = 1 << 0, /* accepts "localhost" or friends. */
|
||||
GET_HOSTNAME_FALLBACK_DEFAULT = 1 << 1, /* use default hostname if no hostname is set. */
|
||||
GET_HOSTNAME_SHORT = 1 << 2, /* kills the FQDN part if present. */
|
||||
} GetHostnameFlags;
|
||||
|
||||
int gethostname_full(GetHostnameFlags flags, char **ret);
|
||||
|
||||
static inline int gethostname_strict(char **ret) {
|
||||
return gethostname_full(0, ret);
|
||||
}
|
||||
|
||||
static inline char* gethostname_malloc(void) {
|
||||
char *s;
|
||||
|
||||
if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT, &s) < 0)
|
||||
return NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline char* gethostname_short_malloc(void) {
|
||||
char *s;
|
||||
|
||||
if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT | GET_HOSTNAME_SHORT, &s) < 0)
|
||||
return NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
#include <sys/auxv.h>
|
||||
|
||||
#include "escape.h"
|
||||
#include "hostname-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "id128-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pidfd-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "macro.h"
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "glyph-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "json-util.h"
|
||||
#include "locale-util.h"
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "io-util.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "ansi-color.h"
|
||||
#include "bus-map-properties.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "memory-util.h"
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "format-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "journal-file.h"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "ima-util.h"
|
||||
|
@ -3,9 +3,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
@ -13,52 +16,95 @@
|
||||
TEST(read_etc_hostname) {
|
||||
_cleanup_(unlink_tempfilep) char path[] = "/tmp/hostname.XXXXXX";
|
||||
char *hostname;
|
||||
int fd;
|
||||
int r;
|
||||
|
||||
fd = mkostemp_safe(path);
|
||||
assert_se(fd > 0);
|
||||
close(fd);
|
||||
safe_close(ASSERT_FD(mkostemp_safe(path)));
|
||||
|
||||
/* simple hostname */
|
||||
assert_se(write_string_file(path, "foo", WRITE_STRING_FILE_CREATE) == 0);
|
||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||
ASSERT_OK(write_string_file(path, "foo", WRITE_STRING_FILE_CREATE));
|
||||
ASSERT_OK(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname));
|
||||
ASSERT_STREQ(hostname, "foo");
|
||||
hostname = mfree(hostname);
|
||||
|
||||
/* with comment */
|
||||
assert_se(write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE) == 0);
|
||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||
assert_se(hostname);
|
||||
ASSERT_OK(write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE));
|
||||
ASSERT_OK(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname));
|
||||
ASSERT_NOT_NULL(hostname);
|
||||
ASSERT_STREQ(hostname, "foo");
|
||||
hostname = mfree(hostname);
|
||||
|
||||
/* with comment and extra whitespace */
|
||||
assert_se(write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE) == 0);
|
||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||
assert_se(hostname);
|
||||
ASSERT_OK(write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE));
|
||||
ASSERT_OK(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname));
|
||||
ASSERT_NOT_NULL(hostname);
|
||||
ASSERT_STREQ(hostname, "foo");
|
||||
hostname = mfree(hostname);
|
||||
|
||||
/* cleans up name */
|
||||
assert_se(write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE) == 0);
|
||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||
assert_se(hostname);
|
||||
ASSERT_OK(write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE));
|
||||
ASSERT_OK(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname));
|
||||
ASSERT_NOT_NULL(hostname);
|
||||
ASSERT_STREQ(hostname, "foobar.com");
|
||||
hostname = mfree(hostname);
|
||||
|
||||
/* with wildcards */
|
||||
ASSERT_OK(write_string_file(path, "foo????????x??????????u", WRITE_STRING_FILE_CREATE));
|
||||
ASSERT_OK(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname));
|
||||
ASSERT_NOT_NULL(hostname);
|
||||
ASSERT_STREQ(hostname, "foo????????x??????????u");
|
||||
hostname = mfree(hostname);
|
||||
r = read_etc_hostname(path, /* substitute_wildcards= */ true, &hostname);
|
||||
if (ERRNO_IS_NEG_MACHINE_ID_UNSET(r))
|
||||
log_tests_skipped("skipping wildcard hostname tests, no machine ID defined");
|
||||
else {
|
||||
ASSERT_OK(r);
|
||||
ASSERT_NOT_NULL(hostname);
|
||||
ASSERT_NULL(strchr(hostname, '?'));
|
||||
ASSERT_EQ(fnmatch("foo????????x??????????u", hostname, /* flags= */ 0), 0);
|
||||
ASSERT_TRUE(hostname_is_valid(hostname, /* flags= */ 0));
|
||||
hostname = mfree(hostname);
|
||||
}
|
||||
|
||||
/* no value set */
|
||||
hostname = (char*) 0x1234;
|
||||
assert_se(write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE) == 0);
|
||||
assert_se(read_etc_hostname(path, &hostname) == -ENOENT);
|
||||
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||
ASSERT_OK(write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_TRUNCATE));
|
||||
ASSERT_ERROR(read_etc_hostname(path, /* substitute_wildcards= */ false, &hostname), ENOENT);
|
||||
assert(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||
|
||||
/* nonexisting file */
|
||||
assert_se(read_etc_hostname("/non/existing", &hostname) == -ENOENT);
|
||||
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||
ASSERT_ERROR(read_etc_hostname("/non/existing", /* substitute_wildcards= */ false, &hostname), ENOENT);
|
||||
assert(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||
}
|
||||
|
||||
TEST(hostname_setup) {
|
||||
hostname_setup(false);
|
||||
}
|
||||
|
||||
TEST(hostname_malloc) {
|
||||
_cleanup_free_ char *h = NULL, *l = NULL;
|
||||
|
||||
assert_se(h = gethostname_malloc());
|
||||
log_info("hostname_malloc: \"%s\"", h);
|
||||
|
||||
assert_se(l = gethostname_short_malloc());
|
||||
log_info("hostname_short_malloc: \"%s\"", l);
|
||||
}
|
||||
|
||||
TEST(default_hostname) {
|
||||
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_NOT_NULL(n);
|
||||
log_info("get_default_hostname: \"%s\"", n);
|
||||
ASSERT_TRUE(hostname_is_valid(n, /* flags= */ 0));
|
||||
|
||||
_cleanup_free_ char *m = get_default_hostname_raw();
|
||||
ASSERT_NOT_NULL(m);
|
||||
log_info("get_default_hostname_raw: \"%s\"", m);
|
||||
ASSERT_TRUE(hostname_is_valid(m, VALID_HOSTNAME_QUESTION_MARK));
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
@ -44,6 +44,9 @@ TEST(hostname_is_valid) {
|
||||
assert_se(!hostname_is_valid("foo..bar", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("foo.bar..", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", VALID_HOSTNAME_TRAILING_DOT));
|
||||
|
||||
ASSERT_FALSE(hostname_is_valid("foo??bar", 0));
|
||||
ASSERT_TRUE(hostname_is_valid("foo??bar", VALID_HOSTNAME_QUESTION_MARK));
|
||||
}
|
||||
|
||||
TEST(hostname_cleanup) {
|
||||
@ -91,26 +94,4 @@ TEST(hostname_cleanup) {
|
||||
ASSERT_STREQ(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||
}
|
||||
|
||||
TEST(hostname_malloc) {
|
||||
_cleanup_free_ char *h = NULL, *l = NULL;
|
||||
|
||||
assert_se(h = gethostname_malloc());
|
||||
log_info("hostname_malloc: \"%s\"", h);
|
||||
|
||||
assert_se(l = gethostname_short_malloc());
|
||||
log_info("hostname_short_malloc: \"%s\"", l);
|
||||
}
|
||||
|
||||
TEST(default_hostname) {
|
||||
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));
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "install-printf.h"
|
||||
#include "install.h"
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "format-ifname.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "local-addresses.h"
|
||||
#include "log.h"
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "all-units.h"
|
||||
#include "glob-util.h"
|
||||
#include "format-util.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "macro.h"
|
||||
#include "manager.h"
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "fs-util.h"
|
||||
#include "gpt.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "io-util.h"
|
||||
#include "kernel-image.h"
|
||||
|
@ -262,6 +262,22 @@ test_varlink() {
|
||||
cmp "$A" "$B"
|
||||
}
|
||||
|
||||
test_wildcard() {
|
||||
SAVED="$(cat /etc/hostname)"
|
||||
|
||||
P='foo-??-??.????bar'
|
||||
hostnamectl set-hostname "$P"
|
||||
H="$(hostname)"
|
||||
# Validate that the hostname is not the literal pattern, but matches the pattern shell style
|
||||
assert_neq "$H" "$P"
|
||||
[[ "$P" == "$H" ]]
|
||||
assert_eq "$(cat /etc/hostname)" "$P"
|
||||
|
||||
assert_in "Static hostname: foo-" "$(hostnamectl)"
|
||||
|
||||
hostnamectl set-hostname "$SAVED"
|
||||
}
|
||||
|
||||
run_testcases
|
||||
|
||||
touch /testok
|
||||
|
Loading…
x
Reference in New Issue
Block a user