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>
27 //#include "fd-util.h"
29 #include "hostname-util.h"
31 #include "string-util.h"
33 #if 0 /// UNNEEDED by elogind
34 bool hostname_is_set(void) {
37 assert_se(uname(&u) >= 0);
39 if (isempty(u.nodename))
42 /* This is the built-in kernel default host name */
43 if (streq(u.nodename, "(none)"))
50 char* gethostname_malloc(void) {
53 /* This call tries to return something useful, either the actual hostname
54 * or it makes something up. The only reason it might fail is OOM.
55 * It might even return "localhost" if that's set. */
57 assert_se(uname(&u) >= 0);
59 if (isempty(u.nodename) || streq(u.nodename, "(none)"))
60 return strdup(u.sysname);
62 return strdup(u.nodename);
65 #if 0 /// UNNEEDED by elogind
66 int gethostname_strict(char **ret) {
70 /* This call will rather fail than make up a name. It will not return "localhost" either. */
72 assert_se(uname(&u) >= 0);
74 if (isempty(u.nodename))
77 if (streq(u.nodename, "(none)"))
80 if (is_localhost(u.nodename))
83 k = strdup(u.nodename);
92 static bool hostname_valid_char(char c) {
94 (c >= 'a' && c <= 'z') ||
95 (c >= 'A' && c <= 'Z') ||
96 (c >= '0' && c <= '9') ||
103 * Check if s looks like a valid host name or FQDN. This does not do
104 * full DNS validation, but only checks if the name is composed of
105 * allowed characters and the length is not above the maximum allowed
106 * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
107 * allow_trailing_dot is true and at least two components are present
108 * in the name. Note that due to the restricted charset and length
109 * this call is substantially more conservative than
110 * dns_name_is_valid().
112 bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
120 /* Doesn't accept empty hostnames, hostnames with
121 * leading dots, and hostnames with multiple dots in a
122 * sequence. Also ensures that the length stays below
125 for (p = s, dot = true; *p; p++) {
133 if (!hostname_valid_char(*p))
140 if (dot && (n_dots < 2 || !allow_trailing_dot))
143 if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on
144 * Linux, but DNS allows domain names
145 * up to 255 characters */
151 #if 0 /// UNNEEDED by elogind
152 char* hostname_cleanup(char *s) {
158 strshorten(s, HOST_NAME_MAX);
160 for (p = s, d = s, dot = true; *p; p++) {
167 } else if (hostname_valid_char(*p)) {
183 bool is_localhost(const char *hostname) {
186 /* This tries to identify local host and domain names
187 * described in RFC6761 plus the redhatism of localdomain */
189 return strcaseeq(hostname, "localhost") ||
190 strcaseeq(hostname, "localhost.") ||
191 strcaseeq(hostname, "localhost.localdomain") ||
192 strcaseeq(hostname, "localhost.localdomain.") ||
193 endswith_no_case(hostname, ".localhost") ||
194 endswith_no_case(hostname, ".localhost.") ||
195 endswith_no_case(hostname, ".localhost.localdomain") ||
196 endswith_no_case(hostname, ".localhost.localdomain.");
199 #if 0 /// UNNEEDED by elogind
200 bool is_gateway_hostname(const char *hostname) {
203 /* This tries to identify the valid syntaxes for the our
204 * synthetic "gateway" host. */
207 strcaseeq(hostname, "gateway") ||
208 strcaseeq(hostname, "gateway.");
211 int sethostname_idempotent(const char *s) {
212 char buf[HOST_NAME_MAX + 1] = {};
216 if (gethostname(buf, sizeof(buf)) < 0)
222 if (sethostname(s, strlen(s)) < 0)
228 int read_hostname_config(const char *path, char **hostname) {
229 _cleanup_fclose_ FILE *f = NULL;
236 f = fopen(path, "re");
240 /* may have comments, ignore them */
241 FOREACH_LINE(l, f, return -errno) {
243 if (l[0] != '\0' && l[0] != '#') {
244 /* found line with value */
245 name = hostname_cleanup(l);
254 /* no non-empty line found */