summary refs log tree commit diff
path: root/src/core/nm-hostname-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/nm-hostname-manager.c')
-rw-r--r--src/core/nm-hostname-manager.c255
1 files changed, 101 insertions, 154 deletions
diff --git a/src/core/nm-hostname-manager.c b/src/core/nm-hostname-manager.c
index 91e9baaa..32dc2db9 100644
--- a/src/core/nm-hostname-manager.c
+++ b/src/core/nm-hostname-manager.c
@@ -10,8 +10,8 @@
 #include <sys/stat.h>
 
 #if HAVE_SELINUX
-    #include <selinux/selinux.h>
-    #include <selinux/label.h>
+#include <selinux/selinux.h>
+#include <selinux/label.h>
 #endif
 
 #include "libnm-core-aux-intern/nm-common-macros.h"
@@ -37,17 +37,17 @@
 #if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) \
      + defined(HOSTNAME_PERSIST_GENTOO))                                  \
     > 1
-    #error "Can only define one of HOSTNAME_PERSIST_*"
+#error "Can only define one of HOSTNAME_PERSIST_*"
 #endif
 
 #if defined(HOSTNAME_PERSIST_SUSE)
-    #define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
+#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
 #elif defined(HOSTNAME_PERSIST_SLACKWARE)
-    #define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
+#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME
 #elif defined(HOSTNAME_PERSIST_GENTOO)
-    #define HOSTNAME_FILE HOSTNAME_FILE_GENTOO
+#define HOSTNAME_FILE HOSTNAME_FILE_GENTOO
 #else
-    #define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT
+#define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT
 #endif
 
 /*****************************************************************************/
@@ -86,6 +86,19 @@ NM_DEFINE_SINGLETON_GETTER(NMHostnameManager, nm_hostname_manager_get, NM_TYPE_H
 
 /*****************************************************************************/
 
+static inline GFileMonitor *
+_file_monitor_new(const char *path)
+{
+    gs_unref_object GFile *file = NULL;
+
+    nm_assert(path);
+
+    file = g_file_new_for_path(path);
+    return g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL);
+}
+
+/*****************************************************************************/
+
 #if defined(HOSTNAME_PERSIST_GENTOO)
 static char *
 read_hostname_gentoo(const char *path)
@@ -162,41 +175,6 @@ hostname_is_dynamic(void)
 }
 #endif
 
-/* Returns an allocated string which the caller owns and must eventually free */
-char *
-nm_hostname_manager_read_hostname(NMHostnameManager *self)
-{
-    NMHostnameManagerPrivate *priv     = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
-    char *                    hostname = NULL;
-
-    if (priv->hostnamed_proxy) {
-        hostname = g_strdup(priv->current_hostname);
-        goto out;
-    }
-
-#if defined(HOSTNAME_PERSIST_SUSE)
-    if (priv->dhcp_monitor_id && hostname_is_dynamic())
-        return NULL;
-#endif
-
-#if defined(HOSTNAME_PERSIST_GENTOO)
-    hostname = read_hostname_gentoo(HOSTNAME_FILE);
-#elif defined(HOSTNAME_PERSIST_SLACKWARE)
-    hostname     = read_hostname_slackware(HOSTNAME_FILE);
-#else
-    if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL))
-        g_strchomp(hostname);
-#endif
-
-out:
-    if (hostname && !hostname[0]) {
-        g_free(hostname);
-        return NULL;
-    }
-
-    return hostname;
-}
-
 /*****************************************************************************/
 
 const char *
@@ -207,76 +185,78 @@ nm_hostname_manager_get_hostname(NMHostnameManager *self)
 }
 
 static void
-_set_hostname_take(NMHostnameManager *self, char *hostname)
+_set_hostname(NMHostnameManager *self, const char *hostname)
 {
     NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
+    char *                    old_hostname;
+
+    hostname = nm_str_not_empty(hostname);
+
+    if (nm_streq0(hostname, priv->current_hostname))
+        return;
 
     _LOGI("hostname changed from %s%s%s to %s%s%s",
           NM_PRINT_FMT_QUOTED(priv->current_hostname, "\"", priv->current_hostname, "\"", "(none)"),
           NM_PRINT_FMT_QUOTED(hostname, "\"", hostname, "\"", "(none)"));
 
-    g_free(priv->current_hostname);
-    priv->current_hostname = hostname;
-    _notify(self, PROP_HOSTNAME);
-}
-
-static void
-_set_hostname(NMHostnameManager *self, const char *hostname)
-{
-    NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
+    old_hostname           = priv->current_hostname;
+    priv->current_hostname = g_strdup(hostname);
+    g_free(old_hostname);
 
-    hostname = nm_str_not_empty(hostname);
-    if (!nm_streq0(hostname, priv->current_hostname))
-        _set_hostname_take(self, g_strdup(hostname));
+    _notify(self, PROP_HOSTNAME);
 }
 
 static void
-_set_hostname_read(NMHostnameManager *self)
+_set_hostname_read_file(NMHostnameManager *self)
 {
-    NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
-    char *                    hostname;
+    NMHostnameManagerPrivate *priv     = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
+    gs_free char *            hostname = NULL;
 
     if (priv->hostnamed_proxy) {
         /* read-hostname returns the current hostname with hostnamed. */
         return;
     }
 
-    hostname = nm_hostname_manager_read_hostname(self);
-
-    if (nm_streq0(hostname, priv->current_hostname)) {
-        g_free(hostname);
+#if defined(HOSTNAME_PERSIST_SUSE)
+    if (priv->dhcp_monitor_id && hostname_is_dynamic())
         return;
-    }
+#endif
+
+#if defined(HOSTNAME_PERSIST_GENTOO)
+    hostname = read_hostname_gentoo(HOSTNAME_FILE);
+#elif defined(HOSTNAME_PERSIST_SLACKWARE)
+    hostname     = read_hostname_slackware(HOSTNAME_FILE);
+#else
+    if (g_file_get_contents(HOSTNAME_FILE, &hostname, NULL, NULL))
+        g_strchomp(hostname);
+#endif
 
-    _set_hostname_take(self, hostname);
+    _set_hostname(self, hostname);
 }
 
 /*****************************************************************************/
 
-typedef struct {
-    char *                         hostname;
-    NMHostnameManagerSetHostnameCb cb;
-    gpointer                       user_data;
-} SetHostnameInfo;
-
 static void
 set_transient_hostname_done(GObject *object, GAsyncResult *res, gpointer user_data)
 {
-    GDBusProxy *proxy                 = G_DBUS_PROXY(object);
-    gs_free SetHostnameInfo *info     = user_data;
-    gs_unref_variant GVariant *result = NULL;
-    gs_free_error GError *error       = NULL;
+    GDBusProxy *     proxy                  = G_DBUS_PROXY(object);
+    gs_unref_variant GVariant *result       = NULL;
+    gs_free_error GError *         error    = NULL;
+    gs_free char *                 hostname = NULL;
+    NMHostnameManagerSetHostnameCb cb;
+    gpointer                       cb_user_data;
+
+    nm_utils_user_data_unpack(user_data, &hostname, &cb, &cb_user_data);
 
     result = g_dbus_proxy_call_finish(proxy, res, &error);
 
     if (error) {
         _LOGW("couldn't set the system hostname to '%s' using hostnamed: %s",
-              info->hostname,
+              hostname,
               error->message);
     }
 
-    info->cb(info->hostname, !error, info->user_data);
-    g_free(info->hostname);
+    cb(hostname, !error, cb_user_data);
 }
 
 void
@@ -286,7 +266,6 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager *            self,
                                            gpointer                       user_data)
 {
     NMHostnameManagerPrivate *priv;
-    SetHostnameInfo *         info;
 
     g_return_if_fail(NM_IS_HOSTNAME_MANAGER(self));
 
@@ -297,11 +276,6 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager *            self,
         return;
     }
 
-    info            = g_new0(SetHostnameInfo, 1);
-    info->hostname  = g_strdup(hostname);
-    info->cb        = cb;
-    info->user_data = user_data;
-
     g_dbus_proxy_call(priv->hostnamed_proxy,
                       "SetHostname",
                       g_variant_new("(sb)", hostname, FALSE),
@@ -309,7 +283,7 @@ nm_hostname_manager_set_transient_hostname(NMHostnameManager *            self,
                       -1,
                       NULL,
                       set_transient_hostname_done,
-                      info);
+                      nm_utils_user_data_pack(g_strdup(hostname), cb, user_data));
 }
 
 gboolean
@@ -428,71 +402,63 @@ nm_hostname_manager_write_hostname(NMHostnameManager *self, const char *hostname
     return TRUE;
 }
 
-gboolean
-nm_hostname_manager_validate_hostname(const char *hostname)
-{
-    const char *p;
-    gboolean    dot = TRUE;
-
-    if (!hostname || !hostname[0])
-        return FALSE;
-
-    for (p = hostname; *p; p++) {
-        if (*p == '.') {
-            if (dot)
-                return FALSE;
-            dot = TRUE;
-        } else {
-            if (!g_ascii_isalnum(*p) && (*p != '-') && (*p != '_'))
-                return FALSE;
-            dot = FALSE;
-        }
-    }
+/*****************************************************************************/
 
-    if (dot)
-        return FALSE;
+static void
+hostnamed_properties_changed(GDBusProxy *proxy,
+                             GVariant *  changed_properties,
+                             char **     invalidated_properties,
+                             gpointer    user_data)
+{
+    NMHostnameManager *       self     = user_data;
+    NMHostnameManagerPrivate *priv     = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
+    gs_unref_variant GVariant *variant = NULL;
 
-    return (p - hostname <= HOST_NAME_MAX);
+    variant = g_dbus_proxy_get_cached_property(priv->hostnamed_proxy, "StaticHostname");
+    if (variant && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING))
+        _set_hostname(self, g_variant_get_string(variant, NULL));
 }
 
+/*****************************************************************************/
+
 static void
-hostname_file_changed_cb(GFileMonitor *    monitor,
-                         GFile *           file,
-                         GFile *           other_file,
-                         GFileMonitorEvent event_type,
-                         gpointer          user_data)
+_file_monitors_file_changed_cb(GFileMonitor *    monitor,
+                               GFile *           file,
+                               GFile *           other_file,
+                               GFileMonitorEvent event_type,
+                               gpointer          user_data)
 {
-    _set_hostname_read(user_data);
+    _set_hostname_read_file(user_data);
 }
 
-/*****************************************************************************/
-
 static void
-hostnamed_properties_changed(GDBusProxy *proxy,
-                             GVariant *  changed_properties,
-                             char **     invalidated_properties,
-                             gpointer    user_data)
+_file_monitors_clear(NMHostnameManager *self)
 {
-    NMHostnameManager *       self = user_data;
     NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
-    GVariant *                v_hostname;
 
-    v_hostname = g_dbus_proxy_get_cached_property(priv->hostnamed_proxy, "StaticHostname");
-    if (v_hostname) {
-        _set_hostname(self, g_variant_get_string(v_hostname, NULL));
-        g_variant_unref(v_hostname);
+    if (priv->monitor) {
+        nm_clear_g_signal_handler(priv->monitor, &priv->monitor_id);
+        g_file_monitor_cancel(priv->monitor);
+        g_clear_object(&priv->monitor);
+    }
+
+    if (priv->dhcp_monitor) {
+        nm_clear_g_signal_handler(priv->dhcp_monitor, &priv->dhcp_monitor_id);
+        g_file_monitor_cancel(priv->dhcp_monitor);
+        g_clear_object(&priv->dhcp_monitor);
     }
 }
 
 static void
-setup_hostname_file_monitors(NMHostnameManager *self)
+_file_monitors_setup(NMHostnameManager *self)
 {
     NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE(self);
     GFileMonitor *            monitor;
     const char *              path      = HOSTNAME_FILE;
-    char *                    link_path = NULL;
+    gs_free char *            link_path = NULL;
     struct stat               file_stat;
-    GFile *                   file;
+
+    _file_monitors_clear(self);
 
     /* resolve the path to the hostname file if it is a symbolic link */
     if (lstat(path, &file_stat) == 0 && S_ISLNK(file_stat.st_mode)
@@ -505,29 +471,24 @@ setup_hostname_file_monitors(NMHostnameManager *self)
     }
 
     /* monitor changes to hostname file */
-    file    = g_file_new_for_path(path);
-    monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL);
-    g_object_unref(file);
-    g_free(link_path);
+    monitor = _file_monitor_new(path);
     if (monitor) {
         priv->monitor_id =
-            g_signal_connect(monitor, "changed", G_CALLBACK(hostname_file_changed_cb), self);
+            g_signal_connect(monitor, "changed", G_CALLBACK(_file_monitors_file_changed_cb), self);
         priv->monitor = monitor;
     }
 
 #if defined(HOSTNAME_PERSIST_SUSE)
     /* monitor changes to dhcp file to know whether the hostname is valid */
-    file    = g_file_new_for_path(CONF_DHCP);
-    monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL);
-    g_object_unref(file);
+    monitor = _file_monitor_new(CONF_DHCP);
     if (monitor) {
         priv->dhcp_monitor_id =
-            g_signal_connect(monitor, "changed", G_CALLBACK(hostname_file_changed_cb), self);
+            g_signal_connect(monitor, "changed", G_CALLBACK(_file_monitors_file_changed_cb), self);
         priv->dhcp_monitor = monitor;
     }
 #endif
 
-    _set_hostname_read(self);
+    _set_hostname_read_file(self);
 }
 
 /*****************************************************************************/
@@ -591,7 +552,7 @@ constructed(GObject *object)
     }
 
     if (!priv->hostnamed_proxy)
-        setup_hostname_file_monitors(self);
+        _file_monitors_setup(self);
 
     G_OBJECT_CLASS(nm_hostname_manager_parent_class)->constructed(object);
 }
@@ -609,21 +570,7 @@ dispose(GObject *object)
         g_clear_object(&priv->hostnamed_proxy);
     }
 
-    if (priv->monitor) {
-        if (priv->monitor_id)
-            g_signal_handler_disconnect(priv->monitor, priv->monitor_id);
-
-        g_file_monitor_cancel(priv->monitor);
-        g_clear_object(&priv->monitor);
-    }
-
-    if (priv->dhcp_monitor) {
-        if (priv->dhcp_monitor_id)
-            g_signal_handler_disconnect(priv->dhcp_monitor, priv->dhcp_monitor_id);
-
-        g_file_monitor_cancel(priv->dhcp_monitor);
-        g_clear_object(&priv->dhcp_monitor);
-    }
+    _file_monitors_clear(self);
 
     nm_clear_g_free(&priv->current_hostname);