mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-22 11:10:24 +01:00
policy: use the hostname setting
Rework update_system_hostname() to use the new properties from the
hostname setting.
In the default configuration where all the 3 boolean properties
hostname.{from-dhcp,from-dns,only-from-default} are true, the behavior
is the same as before.
This commit is contained in:
parent
abd002642f
commit
09c8387114
3 changed files with 465 additions and 77 deletions
|
|
@ -206,6 +206,23 @@ typedef struct {
|
||||||
NMEthtoolRingState * ring;
|
NMEthtoolRingState * ring;
|
||||||
} EthtoolState;
|
} EthtoolState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RESOLVER_WAIT_ADDRESS = 0,
|
||||||
|
RESOLVER_IN_PROGRESS,
|
||||||
|
RESOLVER_DONE,
|
||||||
|
} ResolverState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ResolverState state;
|
||||||
|
GResolver * resolver;
|
||||||
|
GInetAddress *address;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
char * hostname;
|
||||||
|
NMDevice * device;
|
||||||
|
guint timeout_id; /* Used when waiting for the address */
|
||||||
|
int addr_family;
|
||||||
|
} HostnameResolver;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -218,6 +235,7 @@ enum {
|
||||||
REMOVED,
|
REMOVED,
|
||||||
RECHECK_AUTO_ACTIVATE,
|
RECHECK_AUTO_ACTIVATE,
|
||||||
RECHECK_ASSUME,
|
RECHECK_ASSUME,
|
||||||
|
DNS_LOOKUP_DONE,
|
||||||
LAST_SIGNAL,
|
LAST_SIGNAL,
|
||||||
};
|
};
|
||||||
static guint signals[LAST_SIGNAL] = {0};
|
static guint signals[LAST_SIGNAL] = {0};
|
||||||
|
|
@ -324,6 +342,14 @@ typedef struct _NMDevicePrivate {
|
||||||
|
|
||||||
int auth_retries;
|
int auth_retries;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
HostnameResolver *hostname_resolver_6;
|
||||||
|
HostnameResolver *hostname_resolver_4;
|
||||||
|
};
|
||||||
|
HostnameResolver *hostname_resolver_x[2];
|
||||||
|
};
|
||||||
|
|
||||||
union {
|
union {
|
||||||
const guint8 hw_addr_len; /* read-only */
|
const guint8 hw_addr_len; /* read-only */
|
||||||
guint8 hw_addr_len_;
|
guint8 hw_addr_len_;
|
||||||
|
|
@ -866,6 +892,22 @@ static NM_UTILS_LOOKUP_STR_DEFINE(mtu_source_to_str,
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_hostname_resolver_free(HostnameResolver *resolver)
|
||||||
|
{
|
||||||
|
if (!resolver)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nm_clear_g_source(&resolver->timeout_id);
|
||||||
|
nm_clear_g_cancellable(&resolver->cancellable);
|
||||||
|
nm_g_object_unref(resolver->resolver);
|
||||||
|
nm_g_object_unref(resolver->address);
|
||||||
|
g_free(resolver->hostname);
|
||||||
|
nm_g_slice_free(resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static NMSettingIP6ConfigPrivacy
|
static NMSettingIP6ConfigPrivacy
|
||||||
_ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr)
|
_ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr)
|
||||||
{
|
{
|
||||||
|
|
@ -15618,6 +15660,7 @@ static void
|
||||||
_cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
|
_cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
|
guint i;
|
||||||
|
|
||||||
_cancel_activation(self);
|
_cancel_activation(self);
|
||||||
|
|
||||||
|
|
@ -15642,6 +15685,9 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
|
||||||
|
|
||||||
nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
|
nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free);
|
||||||
|
|
||||||
_cleanup_ip_pre(self, AF_INET, cleanup_type);
|
_cleanup_ip_pre(self, AF_INET, cleanup_type);
|
||||||
_cleanup_ip_pre(self, AF_INET6, cleanup_type);
|
_cleanup_ip_pre(self, AF_INET6, cleanup_type);
|
||||||
}
|
}
|
||||||
|
|
@ -17467,6 +17513,178 @@ nm_device_auth_retries_try_next(NMDevice *self)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer user_data)
|
||||||
|
{
|
||||||
|
HostnameResolver *resolver;
|
||||||
|
NMDevice * self;
|
||||||
|
gs_free char * hostname = NULL;
|
||||||
|
gs_free char * addr_str = NULL;
|
||||||
|
gs_free_error GError *error = NULL;
|
||||||
|
|
||||||
|
hostname = g_resolver_lookup_by_address_finish(G_RESOLVER(source), result, &error);
|
||||||
|
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
|
return;
|
||||||
|
|
||||||
|
resolver = user_data;
|
||||||
|
self = resolver->device;
|
||||||
|
resolver->state = RESOLVER_DONE;
|
||||||
|
resolver->hostname = g_strdup(hostname);
|
||||||
|
|
||||||
|
_LOGD(LOGD_DNS,
|
||||||
|
"hostname-from-dns: lookup done for %s, result %s%s%s",
|
||||||
|
(addr_str = g_inet_address_to_string(resolver->address)),
|
||||||
|
NM_PRINT_FMT_QUOTE_STRING(hostname));
|
||||||
|
|
||||||
|
nm_clear_g_cancellable(&resolver->cancellable);
|
||||||
|
g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
hostname_dns_address_timeout(gpointer user_data)
|
||||||
|
{
|
||||||
|
HostnameResolver *resolver = user_data;
|
||||||
|
NMDevice * self = resolver->device;
|
||||||
|
|
||||||
|
g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE);
|
||||||
|
|
||||||
|
nm_assert(resolver->state == RESOLVER_WAIT_ADDRESS);
|
||||||
|
nm_assert(!resolver->address);
|
||||||
|
nm_assert(!resolver->cancellable);
|
||||||
|
|
||||||
|
_LOGT(LOGD_DNS,
|
||||||
|
"hostname-from-dns: timed out while waiting IPv%c address",
|
||||||
|
nm_utils_addr_family_to_char(resolver->addr_family));
|
||||||
|
|
||||||
|
resolver->timeout_id = 0;
|
||||||
|
resolver->state = RESOLVER_DONE;
|
||||||
|
g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return value is valid only immediately */
|
||||||
|
const char *
|
||||||
|
nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_wait)
|
||||||
|
{
|
||||||
|
NMDevicePrivate * priv;
|
||||||
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
|
HostnameResolver *resolver;
|
||||||
|
NMIPConfig * ip_config;
|
||||||
|
const char * method;
|
||||||
|
gboolean address_changed = FALSE;
|
||||||
|
gs_unref_object GInetAddress *new_address = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
|
||||||
|
priv = NM_DEVICE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
/* If the device is not supposed to have addresses,
|
||||||
|
* return an immediate empty result.*/
|
||||||
|
method = nm_device_get_effective_ip_config_method(self, addr_family);
|
||||||
|
if (IS_IPv4) {
|
||||||
|
if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
|
||||||
|
nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free);
|
||||||
|
NM_SET_OUT(out_wait, FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (NM_IN_STRSET(method,
|
||||||
|
NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
|
||||||
|
NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
|
||||||
|
nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free);
|
||||||
|
NM_SET_OUT(out_wait, FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolver = priv->hostname_resolver_x[IS_IPv4];
|
||||||
|
if (!resolver) {
|
||||||
|
resolver = g_slice_new(HostnameResolver);
|
||||||
|
*resolver = (HostnameResolver){
|
||||||
|
.resolver = g_resolver_get_default(),
|
||||||
|
.device = self,
|
||||||
|
.addr_family = addr_family,
|
||||||
|
.state = RESOLVER_WAIT_ADDRESS,
|
||||||
|
};
|
||||||
|
priv->hostname_resolver_x[IS_IPv4] = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the first address of the interface and
|
||||||
|
* whether it changed from the previous lookup */
|
||||||
|
ip_config = priv->ip_config_x[IS_IPv4];
|
||||||
|
if (ip_config) {
|
||||||
|
const NMPlatformIPAddress *addr;
|
||||||
|
|
||||||
|
addr = nm_ip_config_get_first_address(ip_config);
|
||||||
|
if (addr) {
|
||||||
|
new_address = g_inet_address_new_from_bytes(addr->address_ptr,
|
||||||
|
IS_IPv4 ? G_SOCKET_FAMILY_IPV4
|
||||||
|
: G_SOCKET_FAMILY_IPV6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_address && resolver->address) {
|
||||||
|
if (!g_inet_address_equal(new_address, resolver->address))
|
||||||
|
address_changed = TRUE;
|
||||||
|
} else if (new_address != resolver->address)
|
||||||
|
address_changed = TRUE;
|
||||||
|
|
||||||
|
{
|
||||||
|
gs_free char *old_str = NULL;
|
||||||
|
gs_free char *new_str = NULL;
|
||||||
|
|
||||||
|
_LOGT(LOGD_DNS,
|
||||||
|
"hostname-from-dns: ipv%c resolver state %d, old address %s, new address %s",
|
||||||
|
nm_utils_addr_family_to_char(resolver->addr_family),
|
||||||
|
resolver->state,
|
||||||
|
resolver->address ? (old_str = g_inet_address_to_string(resolver->address))
|
||||||
|
: "(null)",
|
||||||
|
new_address ? (new_str = g_inet_address_to_string(new_address)) : "(null)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In every state, if the address changed, we restart
|
||||||
|
* the resolution with the new address */
|
||||||
|
if (address_changed) {
|
||||||
|
nm_clear_g_cancellable(&resolver->cancellable);
|
||||||
|
nm_g_object_unref(resolver->address);
|
||||||
|
resolver->state = RESOLVER_WAIT_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address_changed && new_address) {
|
||||||
|
gs_free char *str = NULL;
|
||||||
|
|
||||||
|
_LOGT(LOGD_DNS,
|
||||||
|
"hostname-from-dns: starting lookup for address %s",
|
||||||
|
(str = g_inet_address_to_string(new_address)));
|
||||||
|
|
||||||
|
resolver->state = RESOLVER_IN_PROGRESS;
|
||||||
|
resolver->cancellable = g_cancellable_new();
|
||||||
|
resolver->address = g_steal_pointer(&new_address);
|
||||||
|
g_resolver_lookup_by_address_async(resolver->resolver,
|
||||||
|
resolver->address,
|
||||||
|
resolver->cancellable,
|
||||||
|
hostname_dns_lookup_callback,
|
||||||
|
resolver);
|
||||||
|
nm_clear_g_source(&resolver->timeout_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (resolver->state) {
|
||||||
|
case RESOLVER_WAIT_ADDRESS:
|
||||||
|
if (!resolver->timeout_id)
|
||||||
|
resolver->timeout_id = g_timeout_add(30000, hostname_dns_address_timeout, resolver);
|
||||||
|
NM_SET_OUT(out_wait, TRUE);
|
||||||
|
return NULL;
|
||||||
|
case RESOLVER_IN_PROGRESS:
|
||||||
|
NM_SET_OUT(out_wait, TRUE);
|
||||||
|
return NULL;
|
||||||
|
case RESOLVER_DONE:
|
||||||
|
NM_SET_OUT(out_wait, FALSE);
|
||||||
|
return resolver->hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nm_assert_unreachable_val(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -18644,6 +18862,16 @@ nm_device_class_init(NMDeviceClass *klass)
|
||||||
NULL,
|
NULL,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
signals[DNS_LOOKUP_DONE] = g_signal_new(NM_DEVICE_DNS_LOOKUP_DONE,
|
||||||
|
G_OBJECT_CLASS_TYPE(object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection defaults from plugins */
|
/* Connection defaults from plugins */
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ nm_device_state_reason_check(NMDeviceStateReason reason)
|
||||||
#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */
|
#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */
|
||||||
|
|
||||||
/* Internal signals */
|
/* Internal signals */
|
||||||
|
#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done"
|
||||||
#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
|
#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
|
||||||
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
||||||
#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
|
#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
|
||||||
|
|
@ -863,4 +864,7 @@ const char *nm_device_state_reason_to_str(NMDeviceStateReason reason);
|
||||||
|
|
||||||
gboolean nm_device_is_vpn(NMDevice *self);
|
gboolean nm_device_is_vpn(NMDevice *self);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_pending);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_DEVICE_H__ */
|
#endif /* __NETWORKMANAGER_DEVICE_H__ */
|
||||||
|
|
|
||||||
310
src/nm-policy.c
310
src/nm-policy.c
|
|
@ -117,6 +117,8 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define _NMLOG_PREFIX_NAME "policy"
|
#define _NMLOG_PREFIX_NAME "policy"
|
||||||
|
#undef _NMLOG_ENABLED
|
||||||
|
#define _NMLOG_ENABLED(level, domain) (nm_logging_enabled((level), (domain)))
|
||||||
#define _NMLOG(level, domain, ...) \
|
#define _NMLOG(level, domain, ...) \
|
||||||
G_STMT_START \
|
G_STMT_START \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -131,6 +133,7 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void update_system_hostname(NMPolicy *self, const char *msg);
|
||||||
static void schedule_activate_all(NMPolicy *self);
|
static void schedule_activate_all(NMPolicy *self);
|
||||||
static void schedule_activate_check(NMPolicy *self, NMDevice *device);
|
static void schedule_activate_check(NMPolicy *self, NMDevice *device);
|
||||||
static NMDevice *get_default_device(NMPolicy *self, int addr_family);
|
static NMDevice *get_default_device(NMPolicy *self, int addr_family);
|
||||||
|
|
@ -671,20 +674,168 @@ lookup_by_address(NMPolicy *self)
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NMDevice *device;
|
||||||
|
int priority;
|
||||||
|
bool from_dhcp : 1;
|
||||||
|
bool from_dns : 1;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
bool ip_6;
|
||||||
|
bool ip_4;
|
||||||
|
};
|
||||||
|
bool ip_x[2];
|
||||||
|
};
|
||||||
|
} DeviceHostnameInfo;
|
||||||
|
|
||||||
|
static int
|
||||||
|
device_hostname_info_compare(gconstpointer a, gconstpointer b)
|
||||||
|
{
|
||||||
|
const DeviceHostnameInfo *info1 = a;
|
||||||
|
const DeviceHostnameInfo *info2 = b;
|
||||||
|
|
||||||
|
NM_CMP_FIELD(info1, info2, priority);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_CON_DEFAULT_NOP("hostname.from-dhcp");
|
||||||
|
NM_CON_DEFAULT_NOP("hostname.from-dns-lookup");
|
||||||
|
NM_CON_DEFAULT_NOP("hostname.only-from-default");
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
device_get_hostname_property_boolean(NMDevice *device, const char *name)
|
||||||
|
{
|
||||||
|
NMSettingHostname *s_hostname;
|
||||||
|
char buf[128];
|
||||||
|
int value;
|
||||||
|
|
||||||
|
nm_assert(NM_IN_STRSET(name,
|
||||||
|
NM_SETTING_HOSTNAME_FROM_DHCP,
|
||||||
|
NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP,
|
||||||
|
NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT));
|
||||||
|
|
||||||
|
s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME);
|
||||||
|
|
||||||
|
if (s_hostname) {
|
||||||
|
g_object_get(s_hostname, name, &value, NULL);
|
||||||
|
if (NM_IN_SET(value, NM_TERNARY_FALSE, NM_TERNARY_TRUE))
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
|
||||||
|
nm_sprintf_buf(buf, "hostname.%s", name),
|
||||||
|
device,
|
||||||
|
NM_TERNARY_FALSE,
|
||||||
|
NM_TERNARY_TRUE,
|
||||||
|
NM_TERNARY_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
device_get_hostname_priority(NMDevice *device)
|
||||||
|
{
|
||||||
|
NMSettingHostname *s_hostname;
|
||||||
|
int priority;
|
||||||
|
|
||||||
|
s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME);
|
||||||
|
if (s_hostname) {
|
||||||
|
priority = nm_setting_hostname_get_priority(s_hostname);
|
||||||
|
if (priority != 0)
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
|
||||||
|
NM_CON_DEFAULT("hostname.priority"),
|
||||||
|
device,
|
||||||
|
G_MININT,
|
||||||
|
G_MAXINT,
|
||||||
|
100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GArray *
|
||||||
|
build_device_hostname_infos(NMPolicy *self)
|
||||||
|
{
|
||||||
|
NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
|
||||||
|
const CList * tmp_clist;
|
||||||
|
NMActiveConnection *ac;
|
||||||
|
GArray * array = NULL;
|
||||||
|
|
||||||
|
nm_manager_for_each_active_connection (priv->manager, ac, tmp_clist) {
|
||||||
|
DeviceHostnameInfo *info;
|
||||||
|
NMDevice * device;
|
||||||
|
gboolean only_from_default;
|
||||||
|
|
||||||
|
device = nm_active_connection_get_device(ac);
|
||||||
|
if (!device)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
only_from_default =
|
||||||
|
device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT);
|
||||||
|
if (only_from_default && ac != priv->default_ac4 && ac != priv->default_ac6)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!array)
|
||||||
|
array = g_array_sized_new(FALSE, FALSE, sizeof(DeviceHostnameInfo), 4);
|
||||||
|
|
||||||
|
info = nm_g_array_append_new(array, DeviceHostnameInfo);
|
||||||
|
*info = (DeviceHostnameInfo){
|
||||||
|
.device = device,
|
||||||
|
.priority = device_get_hostname_priority(device),
|
||||||
|
.from_dhcp =
|
||||||
|
device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_FROM_DHCP),
|
||||||
|
.from_dns =
|
||||||
|
device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP),
|
||||||
|
.ip_4 = priv->default_ac4 || !only_from_default,
|
||||||
|
.ip_6 = priv->default_ac6 || !only_from_default,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array && array->len > 1) {
|
||||||
|
const DeviceHostnameInfo *info0;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_array_sort(array, device_hostname_info_compare);
|
||||||
|
|
||||||
|
info0 = &g_array_index(array, DeviceHostnameInfo, 0);
|
||||||
|
if (info0->priority < 0) {
|
||||||
|
for (i = 1; i < array->len; i++) {
|
||||||
|
const DeviceHostnameInfo *info = &g_array_index(array, DeviceHostnameInfo, i);
|
||||||
|
|
||||||
|
if (info->priority > info0->priority) {
|
||||||
|
g_array_set_size(array, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
device_dns_lookup_done(NMDevice *device, gpointer user_data)
|
||||||
|
{
|
||||||
|
NMPolicy *self = user_data;
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
|
||||||
|
|
||||||
|
update_system_hostname(self, "lookup finished");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_system_hostname(NMPolicy *self, const char *msg)
|
update_system_hostname(NMPolicy *self, const char *msg)
|
||||||
{
|
{
|
||||||
NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
|
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
|
||||||
const char * configured_hostname;
|
const char * configured_hostname;
|
||||||
gs_free char * temp_hostname = NULL;
|
gs_free char * temp_hostname = NULL;
|
||||||
const char * dhcp_hostname, *p;
|
const char * dhcp_hostname, *p;
|
||||||
NMIP4Config * ip4_config;
|
gboolean external_hostname = FALSE;
|
||||||
NMIP6Config * ip6_config;
|
NMDhcpConfig * dhcp_config;
|
||||||
gboolean external_hostname = FALSE;
|
gs_unref_array GArray *infos = NULL;
|
||||||
const NMPlatformIP4Address *addr4;
|
DeviceHostnameInfo * info;
|
||||||
const NMPlatformIP6Address *addr6;
|
guint i;
|
||||||
NMDevice * device;
|
int IS_IPv4;
|
||||||
NMDhcpConfig * dhcp_config;
|
|
||||||
|
|
||||||
g_return_if_fail(self != NULL);
|
g_return_if_fail(self != NULL);
|
||||||
|
|
||||||
|
|
@ -724,10 +875,9 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||||
/* Hostname precedence order:
|
/* Hostname precedence order:
|
||||||
*
|
*
|
||||||
* 1) a configured hostname (from settings)
|
* 1) a configured hostname (from settings)
|
||||||
* 2) automatic hostname from the default device's config (DHCP, VPN, etc)
|
* 2) automatic hostname from DHCP of eligible interfaces
|
||||||
* 3) the last hostname set outside NM
|
* 3) reverse-DNS lookup of the first address on eligible interfaces
|
||||||
* 4) reverse-DNS of the best device's IPv4 address
|
* 4) the last hostname set outside NM
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Try a persistent hostname first */
|
/* Try a persistent hostname first */
|
||||||
|
|
@ -738,40 +888,73 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->default_ac4) {
|
infos = build_device_hostname_infos(self);
|
||||||
/* Grab a hostname out of the device's DHCP4 config */
|
|
||||||
dhcp_config = nm_device_get_dhcp_config(get_default_device(self, AF_INET), AF_INET);
|
if (infos && _LOGT_ENABLED(LOGD_DNS)) {
|
||||||
if (dhcp_config) {
|
_LOGT(LOGD_DNS, "device hostname info:");
|
||||||
dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "host_name");
|
for (i = 0; i < infos->len; i++) {
|
||||||
if (dhcp_hostname && dhcp_hostname[0]) {
|
info = &g_array_index(infos, DeviceHostnameInfo, i);
|
||||||
p = nm_str_skip_leading_spaces(dhcp_hostname);
|
_LOGT(LOGD_DNS,
|
||||||
if (p[0]) {
|
" - prio:%4d ipv:%c%c dhcp:%d dns:%d dev:%s",
|
||||||
_set_hostname(self, p, "from DHCPv4");
|
info->priority,
|
||||||
priv->dhcp_hostname = TRUE;
|
info->ip_4 ? '4' : '-',
|
||||||
return;
|
info->ip_6 ? '6' : '-',
|
||||||
}
|
info->from_dhcp,
|
||||||
_LOGW(LOGD_DNS,
|
info->from_dns,
|
||||||
"set-hostname: DHCPv4-provided hostname '%s' looks invalid; ignoring it",
|
nm_device_get_iface(info->device));
|
||||||
dhcp_hostname);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->default_ac6) {
|
for (i = 0; infos && i < infos->len; i++) {
|
||||||
/* Grab a hostname out of the device's DHCP6 config */
|
info = &g_array_index(infos, DeviceHostnameInfo, i);
|
||||||
dhcp_config = nm_device_get_dhcp_config(get_default_device(self, AF_INET6), AF_INET6);
|
g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self);
|
||||||
if (dhcp_config) {
|
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||||
dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "fqdn_fqdn");
|
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
|
||||||
if (dhcp_hostname && dhcp_hostname[0]) {
|
|
||||||
p = nm_str_skip_leading_spaces(dhcp_hostname);
|
if (info->from_dhcp && info->ip_x[IS_IPv4]) {
|
||||||
if (p[0]) {
|
dhcp_config = nm_device_get_dhcp_config(info->device, addr_family);
|
||||||
_set_hostname(self, p, "from DHCPv6");
|
if (dhcp_config) {
|
||||||
priv->dhcp_hostname = TRUE;
|
dhcp_hostname =
|
||||||
return;
|
nm_dhcp_config_get_option(dhcp_config, IS_IPv4 ? "host_name" : "fqdn_fqdn");
|
||||||
|
if (dhcp_hostname && dhcp_hostname[0]) {
|
||||||
|
p = nm_str_skip_leading_spaces(dhcp_hostname);
|
||||||
|
if (p[0]) {
|
||||||
|
_set_hostname(self, p, IS_IPv4 ? "from DHCPv4" : "from DHCPv6");
|
||||||
|
priv->dhcp_hostname = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_LOGW(LOGD_DNS,
|
||||||
|
"set-hostname: DHCPv%c-provided hostname '%s' looks invalid; "
|
||||||
|
"ignoring it",
|
||||||
|
nm_utils_addr_family_to_char(addr_family),
|
||||||
|
dhcp_hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->hostname_mode != NM_POLICY_HOSTNAME_MODE_DHCP) {
|
||||||
|
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||||
|
const int addr_family = IS_IPv4 ? AF_INET6 : AF_INET;
|
||||||
|
|
||||||
|
if (info->from_dns && info->ip_x[IS_IPv4]) {
|
||||||
|
const char *result;
|
||||||
|
gboolean wait;
|
||||||
|
|
||||||
|
result =
|
||||||
|
nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait);
|
||||||
|
if (result) {
|
||||||
|
_set_hostname(self, result, "from address lookup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wait) {
|
||||||
|
g_signal_connect(info->device,
|
||||||
|
NM_DEVICE_DNS_LOOKUP_DONE,
|
||||||
|
(GCallback) device_dns_lookup_done,
|
||||||
|
self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_LOGW(LOGD_DNS,
|
|
||||||
"set-hostname: DHCPv6-provided hostname '%s' looks invalid; ignoring it",
|
|
||||||
dhcp_hostname);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -795,14 +978,6 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||||
|
|
||||||
priv->dhcp_hostname = FALSE;
|
priv->dhcp_hostname = FALSE;
|
||||||
|
|
||||||
if (!priv->default_ac4 && !priv->default_ac6) {
|
|
||||||
/* 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
|
/* If no automatically-configured hostname, try using the last hostname
|
||||||
* set externally to NM
|
* set externally to NM
|
||||||
*/
|
*/
|
||||||
|
|
@ -811,30 +986,7 @@ update_system_hostname(NMPolicy *self, const char *msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No configured hostname, no automatically determined hostname, and no
|
_set_hostname(self, NULL, "no hostname found");
|
||||||
* bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address.
|
|
||||||
*/
|
|
||||||
device = get_default_device(self, AF_INET);
|
|
||||||
ip4_config = device ? nm_device_get_ip4_config(device) : NULL;
|
|
||||||
|
|
||||||
device = get_default_device(self, AF_INET6);
|
|
||||||
ip6_config = device ? nm_device_get_ip6_config(device) : NULL;
|
|
||||||
|
|
||||||
if (ip4_config && (addr4 = nm_ip4_config_get_first_address(ip4_config))) {
|
|
||||||
g_clear_object(&priv->lookup.addr);
|
|
||||||
priv->lookup.addr =
|
|
||||||
g_inet_address_new_from_bytes((guint8 *) &addr4->address, G_SOCKET_FAMILY_IPV4);
|
|
||||||
} else if (ip6_config && (addr6 = nm_ip6_config_get_first_address(ip6_config))) {
|
|
||||||
g_clear_object(&priv->lookup.addr);
|
|
||||||
priv->lookup.addr =
|
|
||||||
g_inet_address_new_from_bytes((guint8 *) &addr6->address, G_SOCKET_FAMILY_IPV6);
|
|
||||||
} else {
|
|
||||||
/* No valid IP config; fall back to localhost.localdomain */
|
|
||||||
_set_hostname(self, NULL, "no IP config");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup_by_address(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1796,6 +1948,8 @@ device_state_changed(NMDevice * device,
|
||||||
|
|
||||||
switch (new_state) {
|
switch (new_state) {
|
||||||
case NM_DEVICE_STATE_FAILED:
|
case NM_DEVICE_STATE_FAILED:
|
||||||
|
g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
|
||||||
|
|
||||||
/* Mark the connection invalid if it failed during activation so that
|
/* Mark the connection invalid if it failed during activation so that
|
||||||
* it doesn't get automatically chosen over and over and over again.
|
* it doesn't get automatically chosen over and over and over again.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1934,6 +2088,8 @@ device_state_changed(NMDevice * device,
|
||||||
ip6_remove_device_prefix_delegations(self, device);
|
ip6_remove_device_prefix_delegations(self, device);
|
||||||
break;
|
break;
|
||||||
case NM_DEVICE_STATE_DISCONNECTED:
|
case NM_DEVICE_STATE_DISCONNECTED:
|
||||||
|
g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
|
||||||
|
|
||||||
/* Reset retry counts for a device's connections when carrier on; if cable
|
/* Reset retry counts for a device's connections when carrier on; if cable
|
||||||
* was unplugged and plugged in again, we should try to reconnect.
|
* was unplugged and plugged in again, we should try to reconnect.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue