core: use hostnamed to set the transient hostname
authorBeniamino Galvani <bgalvani@redhat.com>
Thu, 18 Feb 2016 17:19:30 +0000 (18:19 +0100)
committerBeniamino Galvani <bgalvani@redhat.com>
Fri, 4 Mar 2016 13:27:09 +0000 (14:27 +0100)
In commit 6dc35e66d45e ("settings: add hostnamed support") we started
to use systemd-hostnamed for setting the system static hostname
(i.e. the one written to /etc/hostname), but nm-policy.c still called
sethostname() to set the transient (dynamic) hostname when this needs
to be changed, for example after a reverse lookup of our dynamic IP
address.

Thus, when using systemd the hostname change failed because process'
capabilities are restricted and sethostname() requires CAP_SYS_ADMIN.

We should set also the transient hostname through hostnamed when this
is available.

https://bugzilla.redhat.com/show_bug.cgi?id=1308974

src/nm-policy.c
src/settings/nm-settings.c
src/settings/nm-settings.h

index bbfc3dd..c564ff0 100644 (file)
@@ -127,9 +127,32 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated)
 
 #define FALLBACK_HOSTNAME4 "localhost.localdomain"
 
-static gboolean
-set_system_hostname (const char *new_hostname, const char *msg)
+static void settings_set_hostname_cb (const char *hostname,
+                                      gboolean result,
+                                      gpointer user_data)
 {
+       int ret = 0;
+
+       if (!result) {
+               ret = sethostname (hostname, strlen (hostname));
+               if (ret != 0) {
+                       int errsv = errno;
+
+                       _LOGW (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
+                              hostname, errsv, strerror (errsv));
+                       if (errsv == EPERM)
+                               _LOGW (LOGD_DNS, "you should use hostnamed when systemd hardening is in effect!");
+               }
+       }
+
+       if (!ret)
+               nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL);
+}
+
+static void
+set_system_hostname (NMPolicy *self, const char *new_hostname, const char *msg)
+{
+       NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
        char old_hostname[HOST_NAME_MAX + 1];
        const char *name;
        int ret;
@@ -147,23 +170,15 @@ set_system_hostname (const char *new_hostname, const char *msg)
                /* Don't set the hostname if it isn't actually changing */
                if (   (new_hostname && !strcmp (old_hostname, new_hostname))
                       || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME4)))
-                       return FALSE;
+                       return;
        }
 
        name = (new_hostname && strlen (new_hostname)) ? new_hostname : FALLBACK_HOSTNAME4;
-
        _LOGI (LOGD_DNS, "setting system hostname to '%s' (%s)", name, msg);
-       ret = sethostname (name, strlen (name));
-       if (ret != 0) {
-               int errsv = errno;
-
-               _LOGW (LOGD_DNS, "couldn't set the system hostname to '%s': (%d) %s",
-                      name, errsv, strerror (errsv));
-               if (errsv == EPERM)
-                       _LOGW (LOGD_DNS, "you should use hostnamed when systemd hardening is in effect!");
-       }
-
-       return (ret == 0);
+       nm_settings_set_transient_hostname (priv->settings,
+                                           name,
+                                           settings_set_hostname_cb,
+                                           NULL);
 }
 
 static void
@@ -205,8 +220,7 @@ _set_hostname (NMPolicy *policy,
 
        nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname);
 
-       if (set_system_hostname (priv->cur_hostname, msg))
-               nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL, NULL, NULL);
+       set_system_hostname (policy, priv->cur_hostname, msg);
 }
 
 static void
index f9bac4d..f090185 100644 (file)
@@ -1527,6 +1527,65 @@ impl_settings_reload_connections (NMSettings *self,
        g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE));
 }
 
+typedef struct {
+       char *hostname;
+       NMSettingsSetHostnameCb 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;
+
+       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, error->message);
+       }
+
+       info->cb (info->hostname, !error, info->user_data);
+       g_free (info->hostname);
+}
+
+void
+nm_settings_set_transient_hostname (NMSettings *self,
+                                    const char *hostname,
+                                    NMSettingsSetHostnameCb cb,
+                                    gpointer user_data)
+{
+       NMSettingsPrivate *priv;
+       SetHostnameInfo *info;
+
+       g_return_if_fail (NM_IS_SETTINGS (self));
+       priv = NM_SETTINGS_GET_PRIVATE (self);
+
+       if (!priv->hostname.hostnamed_proxy) {
+               cb (hostname, FALSE, user_data);
+               return;
+       }
+
+       info = g_new0 (SetHostnameInfo, 1);
+       info->hostname = g_strdup (hostname);
+       info->cb = cb;
+       info->user_data = user_data;
+
+       g_dbus_proxy_call (priv->hostname.hostnamed_proxy,
+                          "SetHostname",
+                          g_variant_new ("(sb)", hostname, FALSE),
+                          G_DBUS_CALL_FLAGS_NONE,
+                          -1,
+                          NULL,
+                          set_transient_hostname_done,
+                          info);
+}
+
 static gboolean
 write_hostname (NMSettingsPrivate *priv, const char *hostname)
 {
index 923b164..051c209 100644 (file)
@@ -71,6 +71,8 @@ typedef struct {
        void (*agent_registered) (NMSettings *self, NMSecretAgent *agent);
 } NMSettingsClass;
 
+typedef void (*NMSettingsSetHostnameCb) (const char *name, gboolean result, gpointer user_data);
+
 GType nm_settings_get_type (void);
 
 NMSettings *nm_settings_new (void);
@@ -127,4 +129,9 @@ gint nm_settings_sort_connections (gconstpointer a, gconstpointer b);
 
 gboolean nm_settings_get_startup_complete (NMSettings *self);
 
+void nm_settings_set_transient_hostname (NMSettings *self,
+                                         const char *hostname,
+                                         NMSettingsSetHostnameCb cb,
+                                         gpointer user_data);
+
 #endif  /* __NM_SETTINGS_H__ */