mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-06 15:30:14 +01:00
policy: detect if the hostname was changed outside NetworkManager
When updating the hostname we can now detect if someone else changed the hostname: if so, search for hostname candidates in the dhcp configuration but avoid to fallback to the hostname saved when NM started or querying dns for a reverse lookup of the current IP.
This commit is contained in:
parent
b7557fa723
commit
d34add6f00
1 changed files with 74 additions and 15 deletions
|
|
@ -87,6 +87,8 @@ typedef struct {
|
|||
|
||||
char *orig_hostname; /* hostname at NM start time */
|
||||
char *cur_hostname; /* hostname we want to assign */
|
||||
char *last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */
|
||||
gboolean changing_hostname; /* hostname set operation still in progress */
|
||||
|
||||
GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
|
||||
} NMPolicyPrivate;
|
||||
|
|
@ -412,6 +414,8 @@ settings_set_hostname_cb (const char *hostname,
|
|||
gboolean result,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPolicy *self = NM_POLICY (user_data);
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
int ret = 0;
|
||||
|
||||
if (!result) {
|
||||
|
|
@ -426,8 +430,10 @@ settings_set_hostname_cb (const char *hostname,
|
|||
}
|
||||
}
|
||||
|
||||
priv->changing_hostname = FALSE;
|
||||
if (!ret)
|
||||
nm_dispatcher_call_hostname (NULL, NULL, NULL);
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
#define HOST_NAME_BUFSIZE (HOST_NAME_MAX + 2)
|
||||
|
|
@ -440,6 +446,15 @@ _get_hostname (NMPolicy *self, char **hostname)
|
|||
|
||||
g_assert (hostname && *hostname == NULL);
|
||||
|
||||
/* If there is an in-progress hostname change, return
|
||||
* the last hostname set as would be set soon...
|
||||
*/
|
||||
if (priv->changing_hostname) {
|
||||
_LOGT (LOGD_DNS, "gethostname: \"%s\" (last on set)", priv->last_hostname);
|
||||
*hostname = g_strdup (priv->last_hostname);
|
||||
return *hostname;
|
||||
}
|
||||
|
||||
/* try to get the hostname via dbus... */
|
||||
if (nm_settings_get_transient_hostname (priv->settings, hostname)) {
|
||||
_LOGT (LOGD_DNS, "gethostname: \"%s\" (from dbus)", *hostname);
|
||||
|
|
@ -521,6 +536,11 @@ _set_hostname (NMPolicy *self,
|
|||
return;
|
||||
}
|
||||
|
||||
/* Keep track of the last set hostname */
|
||||
g_free (priv->last_hostname);
|
||||
priv->last_hostname = g_strdup (name);
|
||||
priv->changing_hostname = TRUE;
|
||||
|
||||
_LOGI (LOGD_DNS, "sethostname: '%s' (%s)", name, msg);
|
||||
|
||||
/* Ask NMSettings to update the transient hostname using its
|
||||
|
|
@ -528,7 +548,7 @@ _set_hostname (NMPolicy *self,
|
|||
nm_settings_set_transient_hostname (priv->settings,
|
||||
name,
|
||||
settings_set_hostname_cb,
|
||||
NULL);
|
||||
g_object_ref (self));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -563,19 +583,43 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6)
|
|||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
char *configured_hostname = NULL;
|
||||
gs_free char *temp_hostname = NULL;
|
||||
const char *dhcp_hostname, *p;
|
||||
NMIP4Config *ip4_config;
|
||||
NMIP6Config *ip6_config;
|
||||
gboolean external_hostname = FALSE;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
nm_clear_g_cancellable (&priv->lookup_cancellable);
|
||||
|
||||
/* Check if the hostname was set externally to NM, so that in that case
|
||||
* we can avoid to fallback to the one we got when we started.
|
||||
* Consider "not specific" hostnames as equal. */
|
||||
if ( _get_hostname (self, &temp_hostname)
|
||||
&& !nm_streq0 (temp_hostname, priv->last_hostname)
|
||||
&& ( nm_utils_is_specific_hostname (temp_hostname)
|
||||
|| nm_utils_is_specific_hostname (priv->last_hostname))) {
|
||||
external_hostname = TRUE;
|
||||
_LOGI (LOGD_DNS, "current hostname was changed outside NetworkManager: '%s'",
|
||||
temp_hostname);
|
||||
|
||||
if (!nm_streq0 (temp_hostname, priv->orig_hostname)) {
|
||||
/* Update original (fallback) hostname */
|
||||
g_free (priv->orig_hostname);
|
||||
if (nm_utils_is_specific_hostname (temp_hostname)) {
|
||||
priv->orig_hostname = temp_hostname;
|
||||
temp_hostname = NULL;
|
||||
} else
|
||||
priv->orig_hostname = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hostname precedence order:
|
||||
*
|
||||
* 1) a configured hostname (from settings)
|
||||
* 2) automatic hostname from the default device's config (DHCP, VPN, etc)
|
||||
* 3) the original hostname when NM started
|
||||
* 3) the last hostname set outside NM
|
||||
* 4) reverse-DNS of the best device's IPv4 address
|
||||
*
|
||||
*/
|
||||
|
|
@ -595,14 +639,6 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6)
|
|||
if (!best6)
|
||||
best6 = get_best_ip6_device (self, TRUE);
|
||||
|
||||
if (!best4 && !best6) {
|
||||
/* No best device; fall back to original hostname or if there wasn't
|
||||
* one, 'localhost.localdomain'
|
||||
*/
|
||||
_set_hostname (self, priv->orig_hostname, "no default device");
|
||||
return;
|
||||
}
|
||||
|
||||
if (best4) {
|
||||
NMDhcp4Config *dhcp4_config;
|
||||
|
||||
|
|
@ -643,8 +679,20 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6)
|
|||
}
|
||||
}
|
||||
|
||||
/* If no automatically-configured hostname, try using the hostname from
|
||||
* when NM started up.
|
||||
/* If an hostname was set outside NetworkManager keep it */
|
||||
if (external_hostname)
|
||||
return;
|
||||
|
||||
if (!best4 && !best6) {
|
||||
/* No best device; fall back to the last hostname set externally
|
||||
* to NM or if there wasn't one, 'localhost.localdomain'
|
||||
*/
|
||||
_set_hostname (self, priv->orig_hostname, "no default device");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If no automatically-configured hostname, try using the last hostname
|
||||
* set externally to NM
|
||||
*/
|
||||
if (priv->orig_hostname) {
|
||||
_set_hostname (self, priv->orig_hostname, "from system startup");
|
||||
|
|
@ -2004,6 +2052,15 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data)
|
|||
/* Re-start the hostname lookup thread if we don't have hostname yet. */
|
||||
if (priv->lookup_addr) {
|
||||
char *str = NULL;
|
||||
gs_free char *hostname = NULL;
|
||||
|
||||
/* Check if the hostname was externally set */
|
||||
if ( _get_hostname (self, &hostname)
|
||||
&& nm_utils_is_specific_hostname (hostname)
|
||||
&& !nm_streq0 (hostname, priv->last_hostname)) {
|
||||
g_clear_object (&priv->lookup_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD (LOGD_DNS, "restarting reverse-lookup thread for address %s",
|
||||
(str = g_inet_address_to_string (priv->lookup_addr)));
|
||||
|
|
@ -2213,11 +2270,12 @@ constructed (GObject *object)
|
|||
|
||||
/* Grab hostname on startup and use that if nothing provides one */
|
||||
if (_get_hostname (self, &hostname)) {
|
||||
/* init last_hostname */
|
||||
priv->last_hostname = hostname;
|
||||
|
||||
/* only cache it if it's a valid hostname */
|
||||
if (nm_utils_is_specific_hostname (hostname))
|
||||
priv->orig_hostname = hostname;
|
||||
else
|
||||
g_free (hostname);
|
||||
priv->orig_hostname = g_strdup (hostname);
|
||||
}
|
||||
|
||||
priv->firewall_manager = g_object_ref (nm_firewall_manager_get ());
|
||||
|
|
@ -2310,6 +2368,7 @@ dispose (GObject *object)
|
|||
|
||||
g_clear_pointer (&priv->orig_hostname, g_free);
|
||||
g_clear_pointer (&priv->cur_hostname, g_free);
|
||||
g_clear_pointer (&priv->last_hostname, g_free);
|
||||
|
||||
if (priv->settings) {
|
||||
g_signal_handlers_disconnect_by_data (priv->settings, priv);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue