diff options
Diffstat (limited to 'src/resolve/resolved-util.c')
-rw-r--r-- | src/resolve/resolved-util.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/resolve/resolved-util.c b/src/resolve/resolved-util.c new file mode 100644 index 0000000..00abada --- /dev/null +++ b/src/resolve/resolved-util.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "dns-def.h" +#include "dns-domain.h" +#include "hostname-util.h" +#include "idn-util.h" +#include "resolved-util.h" +#include "utf8.h" + +int resolve_system_hostname(char **full_hostname, char **first_label) { + _cleanup_free_ char *h = NULL, *n = NULL; +#if HAVE_LIBIDN2 + _cleanup_free_ char *utf8 = NULL; +#elif HAVE_LIBIDN + int k; +#endif + char label[DNS_LABEL_MAX]; + const char *p, *decoded; + int r; + + /* Return the full hostname in *full_hostname, if nonnull. + * + * Extract and normalize the first label of the locally configured hostname, check it's not + * "localhost", and return it in *first_label, if nonnull. */ + + r = gethostname_strict(&h); + if (r < 0) + return log_debug_errno(r, "Can't determine system hostname: %m"); + + p = h; + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r < 0) + return log_debug_errno(r, "Failed to unescape hostname: %m"); + if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Couldn't find a single label in hostname."); + +#if HAVE_LIBIDN || HAVE_LIBIDN2 + r = dlopen_idn(); + if (r < 0) { + log_debug_errno(r, "Failed to initialize IDN support, ignoring: %m"); + decoded = label; /* no decoding */ + } else +#endif + { +#if HAVE_LIBIDN2 + r = sym_idn2_to_unicode_8z8z(label, &utf8, 0); + if (r != IDN2_OK) + return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Failed to undo IDNA: %s", sym_idn2_strerror(r)); + assert(utf8_is_valid(utf8)); + + r = strlen(utf8); + decoded = utf8; +#elif HAVE_LIBIDN + k = dns_label_undo_idna(label, r, label, sizeof label); + if (k < 0) + return log_debug_errno(k, "Failed to undo IDNA: %m"); + if (k > 0) + r = k; + + if (!utf8_is_valid(label)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "System hostname is not UTF-8 clean."); + decoded = label; +#else + decoded = label; /* no decoding */ +#endif + } + + r = dns_label_escape_new(decoded, r, &n); + if (r < 0) + return log_debug_errno(r, "Failed to escape hostname: %m"); + + if (is_localhost(n)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "System hostname is 'localhost', ignoring."); + + if (full_hostname) + *full_hostname = TAKE_PTR(h); + if (first_label) + *first_label = TAKE_PTR(n); + return 0; +} |