]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-etc-hosts.c
tree-wide: use "hostname" spelling everywhere
[thirdparty/systemd.git] / src / resolve / resolved-etc-hosts.c
index 8074612fb47b30d36ad2fef678177dffbe72bc1c..2cb06c098da929f1b3ad4c63395226d22fd39fee 100644 (file)
@@ -1,11 +1,15 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include "def.h"
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include "fd-util.h"
 #include "fileio.h"
 #include "hostname-util.h"
 #include "resolved-dns-synthesize.h"
 #include "resolved-etc-hosts.h"
+#include "socket-netlink.h"
 #include "string-util.h"
 #include "strv.h"
 #include "time-util.h"
 /* Recheck /etc/hosts at most once every 2s */
 #define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC)
 
-static inline void etc_hosts_item_free(EtcHostsItem *item) {
+static void etc_hosts_item_free(EtcHostsItem *item) {
         strv_free(item->names);
         free(item);
 }
 
-static inline void etc_hosts_item_by_name_free(EtcHostsItemByName *item) {
+static void etc_hosts_item_by_name_free(EtcHostsItemByName *item) {
         free(item->name);
         free(item->addresses);
         free(item);
@@ -33,6 +37,8 @@ void etc_hosts_free(EtcHosts *hosts) {
 void manager_etc_hosts_flush(Manager *m) {
         etc_hosts_free(&m->etc_hosts);
         m->etc_hosts_mtime = USEC_INFINITY;
+        m->etc_hosts_ino = 0;
+        m->etc_hosts_dev = 0;
 }
 
 static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
@@ -47,19 +53,20 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
 
         r = extract_first_word(&line, &address_str, NULL, EXTRACT_RELAX);
         if (r < 0)
-                return log_error_errno(r, "Couldn't extract address, in line /etc/hosts:%u.", nr);
-        if (r == 0) {
-                log_error("Premature end of line, in line /etc/hosts:%u.", nr);
-                return -EINVAL;
-        }
+                return log_error_errno(r, "/etc/hosts:%u: failed to extract address: %m", nr);
+        assert(r > 0); /* We already checked that the line is not empty, so it should contain *something* */
 
         r = in_addr_ifindex_from_string_auto(address_str, &address.family, &address.address, NULL);
-        if (r < 0)
-                return log_error_errno(r, "Address '%s' is invalid, in line /etc/hosts:%u.", address_str, nr);
+        if (r < 0) {
+                log_warning_errno(r, "/etc/hosts:%u: address '%s' is invalid, ignoring: %m", nr, address_str);
+                return 0;
+        }
 
         r = in_addr_is_null(address.family, &address.address);
-        if (r < 0)
-                return r;
+        if (r < 0) {
+                log_warning_errno(r, "/etc/hosts:%u: address '%s' is invalid, ignoring: %m", nr, address_str);
+                return 0;
+        }
         if (r > 0)
                 /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to
                  * nothing. */
@@ -93,16 +100,18 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
 
                 r = extract_first_word(&line, &name, NULL, EXTRACT_RELAX);
                 if (r < 0)
-                        return log_error_errno(r, "Couldn't extract host name, in line /etc/hosts:%u.", nr);
+                        return log_error_errno(r, "/etc/hosts:%u: couldn't extract hostname: %m", nr);
                 if (r == 0)
                         break;
 
-                r = dns_name_is_valid(name);
-                if (r <= 0)
-                        return log_error_errno(r, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u.", name, nr);
-
                 found = true;
 
+                r = dns_name_is_valid_ldh(name);
+                if (r <= 0) {
+                        log_warning_errno(r, "/etc/hosts:%u: hostname \"%s\" is not valid, ignoring.", nr, name);
+                        continue;
+                }
+
                 if (is_localhost(name))
                         /* Suppress the "localhost" line that is often seen */
                         continue;
@@ -152,10 +161,8 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
                 bn->addresses[bn->n_addresses++] = &item->address;
         }
 
-        if (!found) {
-                log_error("Line is missing any host names, in line /etc/hosts:%u.", nr);
-                return -EINVAL;
-        }
+        if (!found)
+                log_warning("/etc/hosts:%u: line is missing any hostnames", nr);
 
         return 0;
 }
@@ -177,11 +184,13 @@ int etc_hosts_parse(EtcHosts *hosts, FILE *f) {
 
                 nr++;
 
+                l = strchr(line, '#');
+                if (l)
+                        *l = '\0';
+
                 l = strstrip(line);
                 if (isempty(l))
                         continue;
-                if (l[0] == '#')
-                        continue;
 
                 r = parse_line(&t, nr, l);
                 if (r < 0)
@@ -217,8 +226,9 @@ static int manager_etc_hosts_read(Manager *m) {
                         return 0;
                 }
 
-                /* Did the mtime change? If not, there's no point in re-reading the file. */
-                if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime)
+                /* Did the mtime or ino/dev change? If not, there's no point in re-reading the file. */
+                if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime &&
+                    st.st_ino == m->etc_hosts_ino && st.st_dev == m->etc_hosts_dev)
                         return 0;
         }
 
@@ -242,6 +252,8 @@ static int manager_etc_hosts_read(Manager *m) {
                 return r;
 
         m->etc_hosts_mtime = timespec_load(&st.st_mtim);
+        m->etc_hosts_ino = st.st_ino;
+        m->etc_hosts_dev = st.st_dev;
         m->etc_hosts_last = ts;
 
         return 1;