]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hostname-util.c
2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/utsname.h>
29 #include "hostname-util.h"
31 #include "string-util.h"
33 bool hostname_is_set(void) {
36 assert_se(uname(&u
) >= 0);
38 if (isempty(u
.nodename
))
41 /* This is the built-in kernel default host name */
42 if (streq(u
.nodename
, "(none)"))
48 char* gethostname_malloc(void) {
51 /* This call tries to return something useful, either the actual hostname
52 * or it makes something up. The only reason it might fail is OOM.
53 * It might even return "localhost" if that's set. */
55 assert_se(uname(&u
) >= 0);
57 if (isempty(u
.nodename
) || streq(u
.nodename
, "(none)"))
58 return strdup(FALLBACK_HOSTNAME
);
60 return strdup(u
.nodename
);
63 int gethostname_strict(char **ret
) {
67 /* This call will rather fail than make up a name. It will not return "localhost" either. */
69 assert_se(uname(&u
) >= 0);
71 if (isempty(u
.nodename
))
74 if (streq(u
.nodename
, "(none)"))
77 if (is_localhost(u
.nodename
))
80 k
= strdup(u
.nodename
);
88 static bool hostname_valid_char(char c
) {
90 (c
>= 'a' && c
<= 'z') ||
91 (c
>= 'A' && c
<= 'Z') ||
92 (c
>= '0' && c
<= '9') ||
93 IN_SET(c
, '-', '_', '.');
97 * Check if s looks like a valid host name or FQDN. This does not do
98 * full DNS validation, but only checks if the name is composed of
99 * allowed characters and the length is not above the maximum allowed
100 * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
101 * allow_trailing_dot is true and at least two components are present
102 * in the name. Note that due to the restricted charset and length
103 * this call is substantially more conservative than
104 * dns_name_is_valid().
106 bool hostname_is_valid(const char *s
, bool allow_trailing_dot
) {
114 /* Doesn't accept empty hostnames, hostnames with
115 * leading dots, and hostnames with multiple dots in a
116 * sequence. Also ensures that the length stays below
119 for (p
= s
, dot
= true; *p
; p
++) {
127 if (!hostname_valid_char(*p
))
134 if (dot
&& (n_dots
< 2 || !allow_trailing_dot
))
137 if (p
-s
> HOST_NAME_MAX
) /* Note that HOST_NAME_MAX is 64 on
138 * Linux, but DNS allows domain names
139 * up to 255 characters */
145 char* hostname_cleanup(char *s
) {
151 strshorten(s
, HOST_NAME_MAX
);
153 for (p
= s
, d
= s
, dot
= true; *p
; p
++) {
160 } else if (hostname_valid_char(*p
)) {
174 bool is_localhost(const char *hostname
) {
177 /* This tries to identify local host and domain names
178 * described in RFC6761 plus the redhatism of localdomain */
180 return strcaseeq(hostname
, "localhost") ||
181 strcaseeq(hostname
, "localhost.") ||
182 strcaseeq(hostname
, "localhost.localdomain") ||
183 strcaseeq(hostname
, "localhost.localdomain.") ||
184 endswith_no_case(hostname
, ".localhost") ||
185 endswith_no_case(hostname
, ".localhost.") ||
186 endswith_no_case(hostname
, ".localhost.localdomain") ||
187 endswith_no_case(hostname
, ".localhost.localdomain.");
190 bool is_gateway_hostname(const char *hostname
) {
193 /* This tries to identify the valid syntaxes for the our
194 * synthetic "gateway" host. */
197 strcaseeq(hostname
, "_gateway") || strcaseeq(hostname
, "_gateway.")
198 #if ENABLE_COMPAT_GATEWAY_HOSTNAME
199 || strcaseeq(hostname
, "gateway") || strcaseeq(hostname
, "gateway.")
204 int sethostname_idempotent(const char *s
) {
205 char buf
[HOST_NAME_MAX
+ 1] = {};
209 if (gethostname(buf
, sizeof(buf
)) < 0)
215 if (sethostname(s
, strlen(s
)) < 0)
221 int read_hostname_config(const char *path
, char **hostname
) {
222 _cleanup_fclose_
FILE *f
= NULL
;
229 f
= fopen(path
, "re");
233 /* may have comments, ignore them */
234 FOREACH_LINE(l
, f
, return -errno
) {
236 if (!IN_SET(l
[0], '\0', '#')) {
237 /* found line with value */
238 name
= hostname_cleanup(l
);
247 /* no non-empty line found */