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
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>
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>
#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);
}
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);
}
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;
dot = false;
hyphen = true;
- } else if (valid_ldh_char(*p)) {
+ } else if (valid_ldh_char(*p) || *p == '?') {
*(d++) = *p;
dot = false;
hyphen = false;
#include "macro.h"
#include "strv.h"
-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_;
(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();
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);
fuzz_setup_logging();
- (void) read_etc_hostname_stream(f, &ret);
+ (void) read_etc_hostname_stream(f, /* substitute_wildcards= */ true, &ret);
return 0;
}
/* 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 */
typedef enum {
/* Read from /etc/hostname */
PROP_STATIC_HOSTNAME,
+ PROP_STATIC_HOSTNAME_SUBSTITUTED_WILDCARDS,
/* Read from /etc/machine-info */
PROP_PRETTY_HOSTNAME,
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;
}
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 ... */
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(
(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;
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;
/* 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,
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");
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);
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,
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");
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");
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);
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)),
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);
}
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");
#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"
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);
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);
}
}
-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);
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).
*/
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) {
}
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)
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;
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. */
#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"
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) {
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);
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) {
ASSERT_STREQ(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
-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);