]>
Commit | Line | Data |
---|---|---|
75c9d6b5 ZJS |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | ||
3 | #include "dns-def.h" | |
4 | #include "dns-domain.h" | |
5 | #include "hostname-util.h" | |
6 | #include "idn-util.h" | |
7 | #include "resolved-util.h" | |
8 | #include "utf8.h" | |
9 | ||
10 | int resolve_system_hostname(char **full_hostname, char **first_label) { | |
11 | _cleanup_free_ char *h = NULL, *n = NULL; | |
12 | #if HAVE_LIBIDN2 | |
13 | _cleanup_free_ char *utf8 = NULL; | |
14 | #elif HAVE_LIBIDN | |
15 | int k; | |
16 | #endif | |
f5de77fa | 17 | char label[DNS_LABEL_MAX+1]; |
75c9d6b5 ZJS |
18 | const char *p, *decoded; |
19 | int r; | |
20 | ||
21 | /* Return the full hostname in *full_hostname, if nonnull. | |
22 | * | |
23 | * Extract and normalize the first label of the locally configured hostname, check it's not | |
24 | * "localhost", and return it in *first_label, if nonnull. */ | |
25 | ||
26 | r = gethostname_strict(&h); | |
27 | if (r < 0) | |
28 | return log_debug_errno(r, "Can't determine system hostname: %m"); | |
29 | ||
30 | p = h; | |
31 | r = dns_label_unescape(&p, label, sizeof label, 0); | |
32 | if (r < 0) | |
33 | return log_debug_errno(r, "Failed to unescape hostname: %m"); | |
34 | if (r == 0) | |
35 | return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), | |
36 | "Couldn't find a single label in hostname."); | |
37 | ||
38 | #if HAVE_LIBIDN || HAVE_LIBIDN2 | |
39 | r = dlopen_idn(); | |
40 | if (r < 0) { | |
41 | log_debug_errno(r, "Failed to initialize IDN support, ignoring: %m"); | |
42 | decoded = label; /* no decoding */ | |
43 | } else | |
44 | #endif | |
45 | { | |
46 | #if HAVE_LIBIDN2 | |
47 | r = sym_idn2_to_unicode_8z8z(label, &utf8, 0); | |
48 | if (r != IDN2_OK) | |
49 | return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), | |
50 | "Failed to undo IDNA: %s", sym_idn2_strerror(r)); | |
51 | assert(utf8_is_valid(utf8)); | |
52 | ||
53 | r = strlen(utf8); | |
54 | decoded = utf8; | |
55 | #elif HAVE_LIBIDN | |
56 | k = dns_label_undo_idna(label, r, label, sizeof label); | |
57 | if (k < 0) | |
58 | return log_debug_errno(k, "Failed to undo IDNA: %m"); | |
59 | if (k > 0) | |
60 | r = k; | |
61 | ||
62 | if (!utf8_is_valid(label)) | |
63 | return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), | |
64 | "System hostname is not UTF-8 clean."); | |
65 | decoded = label; | |
66 | #else | |
67 | decoded = label; /* no decoding */ | |
68 | #endif | |
69 | } | |
70 | ||
71 | r = dns_label_escape_new(decoded, r, &n); | |
72 | if (r < 0) | |
73 | return log_debug_errno(r, "Failed to escape hostname: %m"); | |
74 | ||
75 | if (is_localhost(n)) | |
76 | return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), | |
77 | "System hostname is 'localhost', ignoring."); | |
78 | ||
79 | if (full_hostname) | |
80 | *full_hostname = TAKE_PTR(h); | |
81 | if (first_label) | |
82 | *first_label = TAKE_PTR(n); | |
83 | return 0; | |
84 | } |