From 5bfb7c3c89afe4da5b1ac2395391e9a986c722f0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 23 Apr 2017 00:40:46 +0200 Subject: [PATCH] hostname: split out hostname management from NMSettings Hostname management is complicated. At least, how it is implemented currently. For example, NMPolicy also sets the hostname (NMPolicy calls nm_settings_set_transient_hostname() to have hostnamed set the hostname, but then falls back to sethostname() in settings_set_hostname_cb()). Also, NMManager tracks the hostname in NM_MANAGER_HOSTNAME too, and NMPolicy listens to changes from there -- instead of changes from NMSettings. Eventually, NMHostnameManager should contain the hostname parts from NMSettings and NMPolicy. --- Makefile.am | 3 + src/nm-hostname-manager.c | 649 +++++++++++++++++++++++++++++++++++++ src/nm-hostname-manager.h | 61 ++++ src/nm-manager.c | 5 +- src/nm-policy.c | 15 +- src/settings/nm-settings.c | 520 +++-------------------------- src/settings/nm-settings.h | 10 - 7 files changed, 764 insertions(+), 499 deletions(-) create mode 100644 src/nm-hostname-manager.c create mode 100644 src/nm-hostname-manager.h diff --git a/Makefile.am b/Makefile.am index 96443196d4..32b6ba65f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1391,6 +1391,9 @@ src_libNetworkManager_la_SOURCES = \ src/ppp/nm-ppp-manager.h \ src/ppp/nm-ppp-status.h \ \ + src/nm-hostname-manager.c \ + src/nm-hostname-manager.h \ + \ src/settings/nm-agent-manager.c \ src/settings/nm-agent-manager.h \ src/settings/nm-inotify-helper.c \ diff --git a/src/nm-hostname-manager.c b/src/nm-hostname-manager.c new file mode 100644 index 0000000000..31132082b5 --- /dev/null +++ b/src/nm-hostname-manager.c @@ -0,0 +1,649 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-hostname-manager.h" + +#include +#include +#include + +#if HAVE_SELINUX +#include +#endif + +#include "nm-common-macros.h" +#include "nm-dbus-interface.h" +#include "nm-connection.h" +#include "nm-utils.h" +#include "nm-core-internal.h" + +#include "NetworkManagerUtils.h" +#include "nm-dispatcher.h" + +/*****************************************************************************/ + +#define HOSTNAMED_SERVICE_NAME "org.freedesktop.hostname1" +#define HOSTNAMED_SERVICE_PATH "/org/freedesktop/hostname1" +#define HOSTNAMED_SERVICE_INTERFACE "org.freedesktop.hostname1" + +#define HOSTNAME_FILE_DEFAULT "/etc/hostname" +#define HOSTNAME_FILE_UCASE_HOSTNAME "/etc/HOSTNAME" +#define HOSTNAME_FILE_GENTOO "/etc/conf.d/hostname" + +#if (defined(HOSTNAME_PERSIST_SUSE) + defined(HOSTNAME_PERSIST_SLACKWARE) + defined(HOSTNAME_PERSIST_GENTOO)) > 1 +#error "Can only define one of HOSTNAME_PERSIST_*" +#endif + +#if defined(HOSTNAME_PERSIST_SUSE) +#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME +#elif defined(HOSTNAME_PERSIST_SLACKWARE) +#define HOSTNAME_FILE HOSTNAME_FILE_UCASE_HOSTNAME +#elif defined(HOSTNAME_PERSIST_GENTOO) +#define HOSTNAME_FILE HOSTNAME_FILE_GENTOO +#else +#define HOSTNAME_FILE HOSTNAME_FILE_DEFAULT +#endif + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMHostnameManager, + PROP_HOSTNAME, +); + +typedef struct { + char *value; + GFileMonitor *monitor; + GFileMonitor *dhcp_monitor; + gulong monitor_id; + gulong dhcp_monitor_id; + GDBusProxy *hostnamed_proxy; +} NMHostnameManagerPrivate; + +struct _NMHostnameManager { + GObject parent; + NMHostnameManagerPrivate _priv; +}; + +struct _NMHostnameManagerClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE (NMHostnameManager, nm_hostname_manager, G_TYPE_OBJECT); + +#define NM_HOSTNAME_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMHostnameManager, NM_IS_HOSTNAME_MANAGER) + +NM_DEFINE_SINGLETON_GETTER (NMHostnameManager, nm_hostname_manager_get, NM_TYPE_HOSTNAME_MANAGER); + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_CORE +#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "hostname", __VA_ARGS__) + +/*****************************************************************************/ + +#if defined(HOSTNAME_PERSIST_GENTOO) +static gchar * +read_hostname_gentoo (const char *path) +{ + gs_free char *contents = NULL; + gs_strfreev char **all_lines = NULL; + const char *tmp; + guint i; + + if (!g_file_get_contents (path, &contents, NULL, NULL)) + return NULL; + + all_lines = g_strsplit (contents, "\n", 0); + for (i = 0; all_lines[i]; i++) { + g_strstrip (all_lines[i]); + if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') + continue; + if (g_str_has_prefix (all_lines[i], "hostname=")) { + tmp = &all_lines[i][NM_STRLEN ("hostname=")]; + return g_shell_unquote (tmp, NULL); + } + } + return NULL; +} +#endif + +#if defined(HOSTNAME_PERSIST_SLACKWARE) +static gchar * +read_hostname_slackware (const char *path) +{ + gs_free char *contents = NULL; + gs_strfreev char **all_lines = NULL; + char *tmp; + guint i, j = 0; + + if (!g_file_get_contents (path, &contents, NULL, NULL)) + return NULL; + + all_lines = g_strsplit (contents, "\n", 0); + for (i = 0; all_lines[i]; i++) { + g_strstrip (all_lines[i]); + if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') + continue; + tmp = &all_lines[i][0]; + /* We only want up to the first '.' -- the rest of the */ + /* fqdn is defined in /etc/hosts */ + while (tmp[j] != '\0') { + if (tmp[j] == '.') { + tmp[j] = '\0'; + break; + } + j++; + } + return g_shell_unquote (tmp, NULL); + } + return NULL; +} +#endif + +#if defined(HOSTNAME_PERSIST_SUSE) +static gboolean +hostname_is_dynamic (void) +{ + GIOChannel *channel; + char *str = NULL; + gboolean dynamic = FALSE; + + channel = g_io_channel_new_file (CONF_DHCP, "r", NULL); + if (!channel) + return dynamic; + + while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) { + if (str) { + g_strstrip (str); + if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME=")) + dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0; + g_free (str); + } + } + + g_io_channel_shutdown (channel, FALSE, NULL); + g_io_channel_unref (channel); + + return dynamic; +} +#endif + +/* Returns an allocated string which the caller owns and must eventually free */ +char * +nm_hostname_manager_get_hostname (NMHostnameManager *self) +{ + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + char *hostname = NULL; + + if (priv->hostnamed_proxy) { + hostname = g_strdup (priv->value); + 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); + hostname = NULL; + } + + return 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; + + 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_hostname_manager_set_transient_hostname (NMHostnameManager *self, + const char *hostname, + NMHostnameManagerSetHostnameCb cb, + gpointer user_data) +{ + NMHostnameManagerPrivate *priv; + SetHostnameInfo *info; + + g_return_if_fail (NM_IS_HOSTNAME_MANAGER (self)); + + priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + + if (!priv->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->hostnamed_proxy, + "SetHostname", + g_variant_new ("(sb)", hostname, FALSE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + set_transient_hostname_done, + info); +} + +gboolean +nm_hostname_manager_get_transient_hostname (NMHostnameManager *self, char **hostname) +{ + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + GVariant *v_hostname; + + if (!priv->hostnamed_proxy) + return FALSE; + + v_hostname = g_dbus_proxy_get_cached_property (priv->hostnamed_proxy, + "Hostname"); + if (!v_hostname) { + _LOGT ("transient hostname retrieval failed"); + return FALSE; + } + + *hostname = g_variant_dup_string (v_hostname, NULL); + g_variant_unref (v_hostname); + + return TRUE; +} + +gboolean +nm_hostname_manager_write_hostname (NMHostnameManager *self, const char *hostname) +{ + NMHostnameManagerPrivate *priv; + char *hostname_eol; + gboolean ret; + gs_free_error GError *error = NULL; + const char *file = HOSTNAME_FILE; + gs_free char *link_path = NULL; + gs_unref_variant GVariant *var = NULL; + struct stat file_stat; +#if HAVE_SELINUX + security_context_t se_ctx_prev = NULL, se_ctx = NULL; + mode_t st_mode = 0; +#endif + + g_return_val_if_fail (NM_IS_HOSTNAME_MANAGER (self), FALSE); + + priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + + if (priv->hostnamed_proxy) { + var = g_dbus_proxy_call_sync (priv->hostnamed_proxy, + "SetStaticHostname", + g_variant_new ("(sb)", hostname, FALSE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error) + _LOGW ("could not set hostname: %s", error->message); + + return !error; + } + + /* If the hostname file is a symbolic link, follow it to find where the + * real file is located, otherwise g_file_set_contents will attempt to + * replace the link with a plain file. + */ + if ( lstat (file, &file_stat) == 0 + && S_ISLNK (file_stat.st_mode) + && (link_path = nm_utils_read_link_absolute (file, NULL))) + file = link_path; + +#if HAVE_SELINUX + /* Get default context for hostname file and set it for fscreate */ + if (stat (file, &file_stat) == 0) + st_mode = file_stat.st_mode; + matchpathcon (file, st_mode, &se_ctx); + matchpathcon_fini (); + getfscreatecon (&se_ctx_prev); + setfscreatecon (se_ctx); +#endif + +#if defined (HOSTNAME_PERSIST_GENTOO) + hostname_eol = g_strdup_printf ("#Generated by NetworkManager\n" + "hostname=\"%s\"\n", hostname); +#else + hostname_eol = g_strdup_printf ("%s\n", hostname); +#endif + + ret = g_file_set_contents (file, hostname_eol, -1, &error); + +#if HAVE_SELINUX + /* Restore previous context and cleanup */ + setfscreatecon (se_ctx_prev); + freecon (se_ctx); + freecon (se_ctx_prev); +#endif + + g_free (hostname_eol); + + if (!ret) { + _LOGW ("could not save hostname to %s: %s", file, error->message); + return FALSE; + } + + 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; + + return (p - hostname <= HOST_NAME_MAX); +} + +static void +hostname_maybe_changed (NMHostnameManager *settings) +{ + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (settings); + char *new_hostname; + + new_hostname = nm_hostname_manager_get_hostname (settings); + + if ( (new_hostname && !priv->value) + || (!new_hostname && priv->value) + || (priv->value && new_hostname && strcmp (priv->value, new_hostname))) { + + _LOGI ("hostname changed from %s%s%s to %s%s%s", + NM_PRINT_FMT_QUOTED (priv->value, "\"", priv->value, "\"", "(none)"), + NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)")); + g_free (priv->value); + priv->value = new_hostname; + _notify (settings, PROP_HOSTNAME); + } else + g_free (new_hostname); +} + +static void +hostname_file_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + hostname_maybe_changed (user_data); +} + +/*****************************************************************************/ + +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); + GVariant *v_hostname; + const char *hostname; + + v_hostname = g_dbus_proxy_get_cached_property (priv->hostnamed_proxy, + "StaticHostname"); + if (!v_hostname) + return; + + hostname = g_variant_get_string (v_hostname, NULL); + + if (g_strcmp0 (priv->value, hostname) != 0) { + _LOGI ("hostname changed from %s%s%s to %s%s%s", + NM_PRINT_FMT_QUOTED (priv->value, "\"", priv->value, "\"", "(none)"), + NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)")); + g_free (priv->value); + priv->value = g_strdup (hostname); + _notify (self, PROP_HOSTNAME); + nm_dispatcher_call_hostname (NULL, NULL, NULL); + } + + g_variant_unref (v_hostname); +} + +static void +setup_hostname_file_monitors (NMHostnameManager *self) +{ + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + GFileMonitor *monitor; + const char *path = HOSTNAME_FILE; + char *link_path = NULL; + struct stat file_stat; + GFile *file; + + priv->value = nm_hostname_manager_get_hostname (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) + && (link_path = nm_utils_read_link_absolute (path, NULL))) { + path = link_path; + if ( lstat(link_path, &file_stat) == 0 + && S_ISLNK (file_stat.st_mode)) { + _LOGW ("only one level of symbolic link indirection is allowed when monitoring " + HOSTNAME_FILE); + } + } + + /* 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); + if (monitor) { + priv->monitor_id = g_signal_connect (monitor, "changed", + G_CALLBACK (hostname_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); + if (monitor) { + priv->dhcp_monitor_id = g_signal_connect (monitor, "changed", + G_CALLBACK (hostname_file_changed_cb), + self); + priv->dhcp_monitor = monitor; + } +#endif + + hostname_maybe_changed (self); +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMHostnameManager *self = NM_HOSTNAME_MANAGER (object); + + switch (prop_id) { + case PROP_HOSTNAME: + g_value_take_string (value, nm_hostname_manager_get_hostname (self)); + + /* Don't ever pass NULL through D-Bus */ + if (!g_value_get_string (value)) + g_value_set_static_string (value, ""); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_hostname_manager_init (NMHostnameManager *self) +{ +} + +static void +constructed (GObject *object) +{ + NMHostnameManager *self = NM_HOSTNAME_MANAGER (object); + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + GDBusProxy *proxy; + GVariant *variant; + gs_free GError *error = NULL; + + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL, + HOSTNAMED_SERVICE_NAME, HOSTNAMED_SERVICE_PATH, + HOSTNAMED_SERVICE_INTERFACE, NULL, &error); + if (proxy) { + variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname"); + if (variant) { + _LOGI ("hostname: using hostnamed"); + priv->hostnamed_proxy = proxy; + g_signal_connect (proxy, "g-properties-changed", + G_CALLBACK (hostnamed_properties_changed), self); + hostnamed_properties_changed (proxy, NULL, NULL, self); + g_variant_unref (variant); + } else { + _LOGI ("hostname: couldn't get property from hostnamed"); + g_object_unref (proxy); + } + } else { + _LOGI ("hostname: hostnamed not used as proxy creation failed with: %s", + error->message); + g_clear_error (&error); + } + + if (!priv->hostnamed_proxy) + setup_hostname_file_monitors (self); + + G_OBJECT_CLASS (nm_hostname_manager_parent_class)->constructed (object); +} + +static void +dispose (GObject *object) +{ + NMHostnameManager *self = NM_HOSTNAME_MANAGER (object); + NMHostnameManagerPrivate *priv = NM_HOSTNAME_MANAGER_GET_PRIVATE (self); + + if (priv->hostnamed_proxy) { + g_signal_handlers_disconnect_by_func (priv->hostnamed_proxy, + G_CALLBACK (hostnamed_properties_changed), + self); + 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); + } + + g_clear_pointer (&priv->value, g_free); + + G_OBJECT_CLASS (nm_hostname_manager_parent_class)->dispose (object); +} + +static void +nm_hostname_manager_class_init (NMHostnameManagerClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->dispose = dispose; + + obj_properties[PROP_HOSTNAME] = + g_param_spec_string (NM_HOSTNAME_MANAGER_HOSTNAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/nm-hostname-manager.h b/src/nm-hostname-manager.h new file mode 100644 index 0000000000..92702bbc1b --- /dev/null +++ b/src/nm-hostname-manager.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager + * + * Søren Sandmann + * Dan Williams + * Tambet Ingo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2007 - 2011, 2017 Red Hat, Inc. + * (C) Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_HOSTNAME_MANAGER_H__ +#define __NM_HOSTNAME_MANAGER_H__ + +#define NM_TYPE_HOSTNAME_MANAGER (nm_hostname_manager_get_type ()) +#define NM_HOSTNAME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManager)) +#define NM_HOSTNAME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManagerClass)) +#define NM_IS_HOSTNAME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HOSTNAME_MANAGER)) +#define NM_IS_HOSTNAME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_HOSTNAME_MANAGER)) +#define NM_HOSTNAME_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_HOSTNAME_MANAGER, NMHostnameManagerClass)) + +#define NM_HOSTNAME_MANAGER_HOSTNAME "hostname" + +typedef struct _NMHostnameManager NMHostnameManager; +typedef struct _NMHostnameManagerClass NMHostnameManagerClass; + +typedef void (*NMHostnameManagerSetHostnameCb) (const char *name, gboolean result, gpointer user_data); + +GType nm_hostname_manager_get_type (void); + +NMHostnameManager *nm_hostname_manager_get (void); + +char *nm_hostname_manager_get_hostname (NMHostnameManager *self); + +gboolean nm_hostname_manager_write_hostname (NMHostnameManager *self, const char *hostname); + +void nm_hostname_manager_set_transient_hostname (NMHostnameManager *self, + const char *hostname, + NMHostnameManagerSetHostnameCb cb, + gpointer user_data); + +gboolean nm_hostname_manager_get_transient_hostname (NMHostnameManager *self, + char **hostname); + +gboolean nm_hostname_manager_validate_hostname (const char *hostname); + +#endif /* __NM_HOSTNAME_MANAGER_H__ */ diff --git a/src/nm-manager.c b/src/nm-manager.c index a74021951a..0d65e58537 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1412,7 +1412,10 @@ system_hostname_changed_cb (NMSettings *settings, NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); char *hostname; - hostname = nm_settings_get_hostname (priv->settings); + g_object_get (priv->settings, + NM_SETTINGS_HOSTNAME, + &hostname, + NULL); /* nm_settings_get_hostname() does not return an empty hostname. */ nm_assert (!hostname || *hostname); diff --git a/src/nm-policy.c b/src/nm-policy.c index 7c74a6b412..24b3cba8c4 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -49,6 +49,7 @@ #include "nm-dhcp6-config.h" #include "nm-config.h" #include "nm-netns.h" +#include "nm-hostname-manager.h" /*****************************************************************************/ @@ -73,6 +74,8 @@ typedef struct { NMSettings *settings; + NMHostnameManager *hostname_manager; + NMDevice *default_device4, *activating_device4; NMDevice *default_device6, *activating_device6; @@ -460,7 +463,7 @@ _get_hostname (NMPolicy *self, char **hostname) } /* try to get the hostname via dbus... */ - if (nm_settings_get_transient_hostname (priv->settings, hostname)) { + if (nm_hostname_manager_get_transient_hostname (priv->hostname_manager, hostname)) { _LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", *hostname); return *hostname; } @@ -549,10 +552,10 @@ _set_hostname (NMPolicy *self, /* Ask NMSettings to update the transient hostname using its * systemd-hostnamed proxy */ - nm_settings_set_transient_hostname (priv->settings, - name, - settings_set_hostname_cb, - g_object_ref (self)); + nm_hostname_manager_set_transient_hostname (priv->hostname_manager, + name, + settings_set_hostname_cb, + g_object_ref (self)); } static void @@ -2300,6 +2303,8 @@ nm_policy_init (NMPolicy *self) priv->netns = g_object_ref (nm_netns_get ()); + priv->hostname_manager = g_object_ref (nm_hostname_manager_get ()); + hostname_mode = nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG, NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index afd1b0849c..2e41f9c3a4 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -76,6 +76,7 @@ #include "NetworkManagerUtils.h" #include "nm-dispatcher.h" #include "nm-inotify-helper.h" +#include "nm-hostname-manager.h" #include "introspection/org.freedesktop.NetworkManager.Settings.h" @@ -94,13 +95,6 @@ EXPORT(nm_settings_connection_replace_and_commit) /*****************************************************************************/ -#define HOSTNAMED_SERVICE_NAME "org.freedesktop.hostname1" -#define HOSTNAMED_SERVICE_PATH "/org/freedesktop/hostname1" -#define HOSTNAMED_SERVICE_INTERFACE "org.freedesktop.hostname1" - -#define HOSTNAME_FILE_DEFAULT "/etc/hostname" -#define HOSTNAME_FILE_UCASE_HOSTNAME "/etc/HOSTNAME" -#define HOSTNAME_FILE_GENTOO "/etc/conf.d/hostname" #define IFCFG_DIR SYSCONFDIR "/sysconfig/network" #define CONF_DHCP IFCFG_DIR "/dhcp" @@ -162,14 +156,9 @@ typedef struct { gboolean started; gboolean startup_complete; - struct { - char *value; - GFileMonitor *monitor; - GFileMonitor *dhcp_monitor; - gulong monitor_id; - gulong dhcp_monitor_id; - GDBusProxy *hostnamed_proxy; - } hostname; + char *hostname; + NMHostnameManager *hostname_manager; + } NMSettingsPrivate; struct _NMSettings { @@ -568,131 +557,6 @@ get_plugin (NMSettings *self, guint32 capability) return NULL; } -#if defined(HOSTNAME_PERSIST_GENTOO) -static gchar * -read_hostname_gentoo (const char *path) -{ - gs_free char *contents = NULL; - gs_strfreev char **all_lines = NULL; - const char *tmp; - guint i; - - if (!g_file_get_contents (path, &contents, NULL, NULL)) - return NULL; - - all_lines = g_strsplit (contents, "\n", 0); - for (i = 0; all_lines[i]; i++) { - g_strstrip (all_lines[i]); - if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') - continue; - if (g_str_has_prefix (all_lines[i], "hostname=")) { - tmp = &all_lines[i][NM_STRLEN ("hostname=")]; - return g_shell_unquote (tmp, NULL); - } - } - return NULL; -} -#endif - -#if defined(HOSTNAME_PERSIST_SLACKWARE) -static gchar * -read_hostname_slackware (const char *path) -{ - gs_free char *contents = NULL; - gs_strfreev char **all_lines = NULL; - char *tmp; - guint i, j = 0; - - if (!g_file_get_contents (path, &contents, NULL, NULL)) - return NULL; - - all_lines = g_strsplit (contents, "\n", 0); - for (i = 0; all_lines[i]; i++) { - g_strstrip (all_lines[i]); - if (all_lines[i][0] == '#' || all_lines[i][0] == '\0') - continue; - tmp = &all_lines[i][0]; - /* We only want up to the first '.' -- the rest of the */ - /* fqdn is defined in /etc/hosts */ - while (tmp[j] != '\0') { - if (tmp[j] == '.') { - tmp[j] = '\0'; - break; - } - j++; - } - return g_shell_unquote (tmp, NULL); - } - return NULL; -} -#endif - -#if defined(HOSTNAME_PERSIST_SUSE) -static gboolean -hostname_is_dynamic (void) -{ - GIOChannel *channel; - char *str = NULL; - gboolean dynamic = FALSE; - - channel = g_io_channel_new_file (CONF_DHCP, "r", NULL); - if (!channel) - return dynamic; - - while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) { - if (str) { - g_strstrip (str); - if (g_str_has_prefix (str, "DHCLIENT_SET_HOSTNAME=")) - dynamic = strcmp (&str[NM_STRLEN ("DHCLIENT_SET_HOSTNAME=")], "\"yes\"") == 0; - g_free (str); - } - } - - g_io_channel_shutdown (channel, FALSE, NULL); - g_io_channel_unref (channel); - - return dynamic; -} -#endif - -/* Returns an allocated string which the caller owns and must eventually free */ -char * -nm_settings_get_hostname (NMSettings *self) -{ - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - char *hostname = NULL; - - if (!priv->started) - return NULL; - - if (priv->hostname.hostnamed_proxy) { - hostname = g_strdup (priv->hostname.value); - goto out; - } - -#if defined(HOSTNAME_PERSIST_SUSE) - if (priv->hostname.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); - hostname = NULL; - } - - return hostname; -} - static gboolean find_spec (GSList *spec_list, const char *spec) { @@ -1626,160 +1490,7 @@ 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); -} - -gboolean -nm_settings_get_transient_hostname (NMSettings *self, char **hostname) -{ - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GVariant *v_hostname; - - if (!priv->hostname.hostnamed_proxy) - return FALSE; - - v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy, - "Hostname"); - if (!v_hostname) { - _LOGT ("transient hostname retrieval failed"); - return FALSE; - } - - *hostname = g_variant_dup_string (v_hostname, NULL); - g_variant_unref (v_hostname); - - return TRUE; -} - -static gboolean -write_hostname (NMSettingsPrivate *priv, const char *hostname) -{ - char *hostname_eol; - gboolean ret; - gs_free_error GError *error = NULL; - const char *file = HOSTNAME_FILE; - gs_free char *link_path = NULL; - gs_unref_variant GVariant *var = NULL; - struct stat file_stat; -#if HAVE_SELINUX - security_context_t se_ctx_prev = NULL, se_ctx = NULL; - mode_t st_mode = 0; -#endif - - if (priv->hostname.hostnamed_proxy) { - var = g_dbus_proxy_call_sync (priv->hostname.hostnamed_proxy, - "SetStaticHostname", - g_variant_new ("(sb)", hostname, FALSE), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (error) - _LOGW ("could not set hostname: %s", error->message); - - return !error; - } - - /* If the hostname file is a symbolic link, follow it to find where the - * real file is located, otherwise g_file_set_contents will attempt to - * replace the link with a plain file. - */ - if ( lstat (file, &file_stat) == 0 - && S_ISLNK (file_stat.st_mode) - && (link_path = nm_utils_read_link_absolute (file, NULL))) - file = link_path; - -#if HAVE_SELINUX - /* Get default context for hostname file and set it for fscreate */ - if (stat (file, &file_stat) == 0) - st_mode = file_stat.st_mode; - matchpathcon (file, st_mode, &se_ctx); - matchpathcon_fini (); - getfscreatecon (&se_ctx_prev); - setfscreatecon (se_ctx); -#endif - -#if defined (HOSTNAME_PERSIST_GENTOO) - hostname_eol = g_strdup_printf ("#Generated by NetworkManager\n" - "hostname=\"%s\"\n", hostname); -#else - hostname_eol = g_strdup_printf ("%s\n", hostname); -#endif - - ret = g_file_set_contents (file, hostname_eol, -1, &error); - -#if HAVE_SELINUX - /* Restore previous context and cleanup */ - setfscreatecon (se_ctx_prev); - freecon (se_ctx); - freecon (se_ctx_prev); -#endif - - g_free (hostname_eol); - - if (!ret) { - _LOGW ("could not save hostname to %s: %s", file, error->message); - return FALSE; - } - - return TRUE; -} +/*****************************************************************************/ static void pk_hostname_cb (NMAuthChain *chain, @@ -1812,7 +1523,7 @@ pk_hostname_cb (NMAuthChain *chain, } else { hostname = nm_auth_chain_get_data (chain, "hostname"); - if (!write_hostname (priv, hostname)) { + if (!nm_hostname_manager_write_hostname (priv->hostname_manager, hostname)) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Saving the hostname failed."); @@ -1827,33 +1538,6 @@ pk_hostname_cb (NMAuthChain *chain, nm_auth_chain_unref (chain); } -static gboolean -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; - - return (p - hostname <= HOST_NAME_MAX); -} - static void impl_settings_save_hostname (NMSettings *self, GDBusMethodInvocation *context, @@ -1864,7 +1548,7 @@ impl_settings_save_hostname (NMSettings *self, GError *error = NULL; /* Minimal validation of the hostname */ - if (!validate_hostname (hostname)) { + if (!nm_hostname_manager_validate_hostname (hostname)) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_HOSTNAME, "The hostname was too long or contained invalid characters."); @@ -1888,37 +1572,7 @@ done: g_dbus_method_invocation_take_error (context, error); } -static void -hostname_maybe_changed (NMSettings *settings) -{ - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (settings); - char *new_hostname; - - new_hostname = nm_settings_get_hostname (settings); - - if ( (new_hostname && !priv->hostname.value) - || (!new_hostname && priv->hostname.value) - || (priv->hostname.value && new_hostname && strcmp (priv->hostname.value, new_hostname))) { - - _LOGI ("hostname changed from %s%s%s to %s%s%s", - NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), - NM_PRINT_FMT_QUOTED (new_hostname, "\"", new_hostname, "\"", "(none)")); - g_free (priv->hostname.value); - priv->hostname.value = new_hostname; - _notify (settings, PROP_HOSTNAME); - } else - g_free (new_hostname); -} - -static void -hostname_file_changed_cb (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) -{ - hostname_maybe_changed (user_data); -} +/*****************************************************************************/ static gboolean have_connection_for_device (NMSettings *self, NMDevice *device) @@ -2141,95 +1795,34 @@ nm_settings_get_startup_complete (NMSettings *self) /*****************************************************************************/ static void -hostnamed_properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - char **invalidated_properties, - gpointer user_data) +_hostname_changed (NMSettings *self) { - NMSettings *self = user_data; NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GVariant *v_hostname; - const char *hostname; + gs_free char *hostname = NULL; - v_hostname = g_dbus_proxy_get_cached_property (priv->hostname.hostnamed_proxy, - "StaticHostname"); - if (!v_hostname) + hostname = nm_hostname_manager_get_hostname (priv->hostname_manager); + + if (nm_streq0 (hostname, priv->hostname)) return; - - hostname = g_variant_get_string (v_hostname, NULL); - - if (g_strcmp0 (priv->hostname.value, hostname) != 0) { - _LOGI ("hostname changed from %s%s%s to %s%s%s", - NM_PRINT_FMT_QUOTED (priv->hostname.value, "\"", priv->hostname.value, "\"", "(none)"), - NM_PRINT_FMT_QUOTED (hostname, "\"", hostname, "\"", "(none)")); - g_free (priv->hostname.value); - priv->hostname.value = g_strdup (hostname); - _notify (self, PROP_HOSTNAME); - nm_dispatcher_call_hostname (NULL, NULL, NULL); - } - - g_variant_unref (v_hostname); + g_free (priv->hostname); + priv->hostname = g_steal_pointer (&hostname); + _notify (self, PROP_HOSTNAME); } static void -setup_hostname_file_monitors (NMSettings *self) +_hostname_changed_cb (NMHostnameManager *hostname_manager, + GParamSpec *pspec, + gpointer user_data) { - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GFileMonitor *monitor; - const char *path = HOSTNAME_FILE; - char *link_path = NULL; - struct stat file_stat; - GFile *file; - - priv->hostname.value = nm_settings_get_hostname (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) - && (link_path = nm_utils_read_link_absolute (path, NULL))) { - path = link_path; - if ( lstat(link_path, &file_stat) == 0 - && S_ISLNK (file_stat.st_mode)) { - _LOGW ("only one level of symbolic link indirection is allowed when monitoring " - HOSTNAME_FILE); - } - } - - /* 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); - if (monitor) { - priv->hostname.monitor_id = g_signal_connect (monitor, "changed", - G_CALLBACK (hostname_file_changed_cb), - self); - priv->hostname.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); - if (monitor) { - priv->hostname.dhcp_monitor_id = g_signal_connect (monitor, "changed", - G_CALLBACK (hostname_file_changed_cb), - self); - priv->hostname.dhcp_monitor = monitor; - } -#endif - - hostname_maybe_changed (self); + _hostname_changed (NM_SETTINGS (user_data)); } +/*****************************************************************************/ + gboolean nm_settings_start (NMSettings *self, GError **error) { NMSettingsPrivate *priv; - GDBusProxy *proxy; - GVariant *variant; - GError *local_error = NULL; gs_strfreev char **plugins = NULL; priv = NM_SETTINGS_GET_PRIVATE (self); @@ -2245,33 +1838,12 @@ nm_settings_start (NMSettings *self, GError **error) load_connections (self); check_startup_complete (self); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, 0, NULL, - HOSTNAMED_SERVICE_NAME, HOSTNAMED_SERVICE_PATH, - HOSTNAMED_SERVICE_INTERFACE, NULL, &local_error); - if (proxy) { - variant = g_dbus_proxy_get_cached_property (proxy, "StaticHostname"); - if (variant) { - _LOGI ("hostname: using hostnamed"); - priv->hostname.hostnamed_proxy = proxy; - g_signal_connect (proxy, "g-properties-changed", - G_CALLBACK (hostnamed_properties_changed), self); - hostnamed_properties_changed (proxy, NULL, NULL, self); - g_variant_unref (variant); - } else { - _LOGI ("hostname: couldn't get property from hostnamed"); - g_object_unref (proxy); - } - } else { - _LOGI ("hostname: hostnamed not used as proxy creation failed with: %s", - local_error->message); - g_clear_error (&local_error); - } - - if (!priv->hostname.hostnamed_proxy) - setup_hostname_file_monitors (self); - - priv->started = TRUE; - _notify (self, PROP_HOSTNAME); + priv->hostname_manager = g_object_ref (nm_hostname_manager_get ()); + g_signal_connect (priv->hostname_manager, + "notify::"NM_HOSTNAME_MANAGER_HOSTNAME, + G_CALLBACK (_hostname_changed_cb), + self); + _hostname_changed (self); return TRUE; } @@ -2298,10 +1870,9 @@ get_property (GObject *object, guint prop_id, g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE)); break; case PROP_HOSTNAME: - g_value_take_string (value, nm_settings_get_hostname (self)); - - /* Don't ever pass NULL through D-Bus */ - if (!g_value_get_string (value)) + if (priv->hostname) + g_value_set_string (value, priv->hostname); + else g_value_set_static_string (value, ""); break; case PROP_CAN_MODIFY: @@ -2362,32 +1933,13 @@ dispose (GObject *object) g_object_unref (priv->agent_mgr); - if (priv->hostname.hostnamed_proxy) { - g_signal_handlers_disconnect_by_func (priv->hostname.hostnamed_proxy, - G_CALLBACK (hostnamed_properties_changed), + if (priv->hostname_manager) { + g_signal_handlers_disconnect_by_func (priv->hostname_manager, + G_CALLBACK (_hostname_changed_cb), self); - g_clear_object (&priv->hostname.hostnamed_proxy); + g_clear_object (&priv->hostname_manager); } - if (priv->hostname.monitor) { - if (priv->hostname.monitor_id) - g_signal_handler_disconnect (priv->hostname.monitor, priv->hostname.monitor_id); - - g_file_monitor_cancel (priv->hostname.monitor); - g_clear_object (&priv->hostname.monitor); - } - - if (priv->hostname.dhcp_monitor) { - if (priv->hostname.dhcp_monitor_id) - g_signal_handler_disconnect (priv->hostname.dhcp_monitor, - priv->hostname.dhcp_monitor_id); - - g_file_monitor_cancel (priv->hostname.dhcp_monitor); - g_clear_object (&priv->hostname.dhcp_monitor); - } - - g_clear_pointer (&priv->hostname.value, g_free); - G_OBJECT_CLASS (nm_settings_parent_class)->dispose (object); } @@ -2405,6 +1957,8 @@ finalize (GObject *object) g_slist_free_full (priv->plugins, g_object_unref); + g_free (priv->hostname); + g_clear_object (&priv->config); G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object); diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 7110a12ba8..eede76b029 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -119,20 +119,10 @@ gboolean nm_settings_has_connection (NMSettings *self, NMSettingsConnection *con const GSList *nm_settings_get_unmanaged_specs (NMSettings *self); -char *nm_settings_get_hostname (NMSettings *self); - void nm_settings_device_added (NMSettings *self, NMDevice *device); void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting); gboolean nm_settings_get_startup_complete (NMSettings *self); -void nm_settings_set_transient_hostname (NMSettings *self, - const char *hostname, - NMSettingsSetHostnameCb cb, - gpointer user_data); - -gboolean nm_settings_get_transient_hostname (NMSettings *self, - char **hostname); - #endif /* __NM_SETTINGS_H__ */