Beniamino Galvani 2020-11-16 17:04:54 +01:00
commit 090c360ca4
30 changed files with 1089 additions and 131 deletions

View file

@ -66,9 +66,12 @@ SpacesInContainerLiterals: false
SpacesInParentheses: false
ForEachMacros: ['c_list_for_each',
'c_list_for_each_prev',
'c_list_for_each_prev_safe',
'c_list_for_each_continue',
'c_list_for_each_entry',
'c_list_for_each_entry_continue',
'c_list_for_each_entry_prev',
'c_list_for_each_entry_safe',
'c_list_for_each_entry_safe_continue',
'c_list_for_each_entry_safe_unlink',
@ -93,7 +96,6 @@ ForEachMacros: ['c_list_for_each',
'ndp_msg_opt_rdnss_for_each_addr',
'nla_for_each_attr',
'nla_for_each_nested',
'nm_c_list_for_each_entry_prev',
'nm_dedup_multi_iter_for_each',
'nm_ip_config_iter_ip4_address_for_each',
'nm_ip_config_iter_ip4_route_for_each',
@ -107,6 +109,7 @@ ForEachMacros: ['c_list_for_each',
'nm_l3_config_data_iter_ip6_route_for_each',
'nm_l3_config_data_iter_obj_for_each',
'nm_manager_for_each_active_connection',
'nm_manager_for_each_active_connection_prev',
'nm_manager_for_each_active_connection_safe',
'nm_manager_for_each_device',
'nm_manager_for_each_device_safe',

View file

@ -943,6 +943,7 @@ libnm_core_lib_h_pub_real = \
libnm-core/nm-setting-ethtool.h \
libnm-core/nm-setting-generic.h \
libnm-core/nm-setting-gsm.h \
libnm-core/nm-setting-hostname.h \
libnm-core/nm-setting-infiniband.h \
libnm-core/nm-setting-ip-config.h \
libnm-core/nm-setting-ip-tunnel.h \
@ -1017,6 +1018,7 @@ libnm_core_lib_c_settings_real = \
libnm-core/nm-setting-ethtool.c \
libnm-core/nm-setting-generic.c \
libnm-core/nm-setting-gsm.c \
libnm-core/nm-setting-hostname.c \
libnm-core/nm-setting-infiniband.c \
libnm-core/nm-setting-ip-config.c \
libnm-core/nm-setting-ip-tunnel.c \

View file

@ -881,7 +881,8 @@ const NmcMetaGenericInfo
"," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME \
"," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME \
"," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME \
"," NM_SETTING_OVS_DPDK_SETTING_NAME /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
"," NM_SETTING_OVS_DPDK_SETTING_NAME \
"," NM_SETTING_HOSTNAME_SETTING_NAME /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
NMC_META_GENERIC_WITH_NESTED("GENERAL", metagen_con_active_general), /* 0 */

View file

@ -564,6 +564,16 @@
<property name="mtu"
description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." />
</setting>
<setting name="hostname" >
<property name="priority"
description="The relative priority of this connection to determine the system hostname. A lower numerical value is better (higher priority). A connection with higher priority is considered before connections with lower priority. If the value is zero, it can be overridden by a global value from NetworkManager configuration. If the property doesn&apos;t have a value in the global configuration, the value is assumed to be 100. Negative values have the special effect of excluding other connections with a greater numerical priority value; so in presence of at least one negative priority, only connections with the lowest priority value will be used to determine the hostname." />
<property name="from-dhcp"
description="Whether the system hostname can be determined from DHCP on this connection. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn&apos;t have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1)." />
<property name="from-dns-lookup"
description="Whether the system hostname can be determined from reverse DNS lookup of addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn&apos;t have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1)." />
<property name="only-from-default"
description="If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to NM_TERNARY_FALSE (0), the hostname can be set from this device even if it doesn&apos;t have the default route. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn&apos;t have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1)." />
</setting>
<setting name="infiniband" >
<property name="mac-address"
alias="mac"

View file

@ -5633,6 +5633,24 @@ static const NMMetaPropertyInfo *const property_infos_GSM[] = {
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_HOSTNAME
static const NMMetaPropertyInfo *const property_infos_HOSTNAME[] = {
PROPERTY_INFO (NM_SETTING_HOSTNAME_PRIORITY, DESCRIBE_DOC_NM_SETTING_HOSTNAME_PRIORITY,
.property_type = &_pt_gobject_int,
),
PROPERTY_INFO (NM_SETTING_HOSTNAME_FROM_DHCP, DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DHCP,
.property_type = &_pt_gobject_enum,
),
PROPERTY_INFO (NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP, DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP,
.property_type = &_pt_gobject_enum,
),
PROPERTY_INFO (NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT, DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT,
.property_type = &_pt_gobject_enum,
),
NULL
};
#undef _CURRENT_NM_META_SETTING_TYPE
#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_INFINIBAND
static const NMMetaPropertyInfo *const property_infos_INFINIBAND[] = {
@ -7936,6 +7954,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN)
#define SETTING_PRETTY_NAME_ETHTOOL N_("Ethtool settings")
#define SETTING_PRETTY_NAME_GENERIC N_("Generic settings")
#define SETTING_PRETTY_NAME_GSM N_("GSM mobile broadband connection")
#define SETTING_PRETTY_NAME_HOSTNAME N_("Hostname settings")
#define SETTING_PRETTY_NAME_INFINIBAND N_("InfiniBand connection")
#define SETTING_PRETTY_NAME_IP4_CONFIG N_("IPv4 protocol")
#define SETTING_PRETTY_NAME_IP6_CONFIG N_("IPv6 protocol")
@ -8073,6 +8092,7 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = {
),
.setting_init_fcn = _setting_init_fcn_gsm,
),
SETTING_INFO (HOSTNAME),
SETTING_INFO (INFINIBAND,
.valid_parts = NM_META_SETTING_VALID_PARTS (
NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE),
@ -8284,6 +8304,7 @@ static const NMMetaSettingValidPartItem *const valid_settings_noslave[] = {
NM_META_SETTING_VALID_PART_ITEM(MATCH, FALSE),
NM_META_SETTING_VALID_PART_ITEM(IP4_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(IP6_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(HOSTNAME, FALSE),
NM_META_SETTING_VALID_PART_ITEM(TC_CONFIG, FALSE),
NM_META_SETTING_VALID_PART_ITEM(PROXY, FALSE),
NULL,

View file

@ -203,6 +203,10 @@
#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_ID N_("The SIM card unique identifier (as given by the WWAN management service) which this connection applies to. If given, the connection will apply to any device also allowed by \"device-id\" which contains a SIM card matching the given identifier.")
#define DESCRIBE_DOC_NM_SETTING_GSM_SIM_OPERATOR_ID N_("A MCC/MNC string like \"310260\" or \"21601\" identifying the specific mobile network operator which this connection applies to. If given, the connection will apply to any device also allowed by \"device-id\" and \"sim-id\" which contains a SIM card provisioned by the given operator.")
#define DESCRIBE_DOC_NM_SETTING_GSM_USERNAME N_("The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here.")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DHCP N_("Whether the system hostname can be determined from DHCP on this connection. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP N_("Whether the system hostname can be determined from reverse DNS lookup of addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT N_("If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device has the default route for the given address family (IPv4/IPv6). If set to NM_TERNARY_FALSE (0), the hostname can be set from this device even if it doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is used. If the property doesn't have a value in the global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE (1).")
#define DESCRIBE_DOC_NM_SETTING_HOSTNAME_PRIORITY N_("The relative priority of this connection to determine the system hostname. A lower numerical value is better (higher priority). A connection with higher priority is considered before connections with lower priority. If the value is zero, it can be overridden by a global value from NetworkManager configuration. If the property doesn't have a value in the global configuration, the value is assumed to be 100. Negative values have the special effect of excluding other connections with a greater numerical priority value; so in presence of at least one negative priority, only connections with the lowest priority value will be used to determine the hostname.")
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MAC_ADDRESS N_("If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing).")
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_MTU N_("If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.")
#define DESCRIBE_DOC_NM_SETTING_INFINIBAND_P_KEY N_("The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka \"the P_Key at index 0\"). Otherwise, it is a 16-bit unsigned integer, whose high bit is set if it is a \"full membership\" P_Key.")

View file

@ -324,6 +324,7 @@ print ("NetworkManager version " + client.get_version())]]></programlisting></in
<xi:include href="xml/nm-setting-ethtool.xml"/>
<xi:include href="xml/nm-setting-generic.xml"/>
<xi:include href="xml/nm-setting-gsm.xml"/>
<xi:include href="xml/nm-setting-hostname.xml"/>
<xi:include href="xml/nm-setting-infiniband.xml"/>
<xi:include href="xml/nm-setting-ip4-config.xml"/>
<xi:include href="xml/nm-setting-ip6-config.xml"/>

View file

@ -33,6 +33,7 @@ libnm_core_headers = files(
'nm-setting-ethtool.h',
'nm-setting-generic.h',
'nm-setting-gsm.h',
'nm-setting-hostname.h',
'nm-setting-infiniband.h',
'nm-setting-ip-config.h',
'nm-setting-ip-tunnel.h',
@ -134,6 +135,7 @@ libnm_core_settings_sources = files(
'nm-setting-ethtool.c',
'nm-setting-generic.c',
'nm-setting-gsm.c',
'nm-setting-hostname.c',
'nm-setting-infiniband.c',
'nm-setting-ip-config.c',
'nm-setting-ip-tunnel.c',

View file

@ -37,6 +37,7 @@
#include "nm-setting-dummy.h"
#include "nm-setting-generic.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-infiniband.h"
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-ip4-config.h"

View file

@ -28,6 +28,7 @@ typedef struct _NMSettingDummy NMSettingDummy;
typedef struct _NMSettingEthtool NMSettingEthtool;
typedef struct _NMSettingGeneric NMSettingGeneric;
typedef struct _NMSettingGsm NMSettingGsm;
typedef struct _NMSettingHostname NMSettingHostname;
typedef struct _NMSettingIP4Config NMSettingIP4Config;
typedef struct _NMSettingIP6Config NMSettingIP6Config;
typedef struct _NMSettingIPConfig NMSettingIPConfig;

View file

@ -0,0 +1,339 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-setting-hostname.h"
#include "nm-setting-private.h"
#include "nm-utils-private.h"
/**
* SECTION:nm-setting-hostname
* @short_description: Contains properties related to the hostname
* @include: nm-setting-hostname.h
**/
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE(NMSettingHostname,
PROP_PRIORITY,
PROP_FROM_DHCP,
PROP_FROM_DNS_LOOKUP,
PROP_ONLY_FROM_DEFAULT, );
/**
* NMSettingHostname:
*
* Hostname settings
*
* Since: 1.30
*/
struct _NMSettingHostname {
NMSetting parent;
int priority;
NMTernary from_dhcp;
NMTernary from_dns_lookup;
NMTernary only_from_default;
};
struct _NMSettingHostnameClass {
NMSettingClass parent;
};
G_DEFINE_TYPE(NMSettingHostname, nm_setting_hostname, NM_TYPE_SETTING)
/**
* nm_setting_hostname_get_priority:
* @setting: the #NMSettingHostname
*
* Returns the value contained in the #NMSettingHostname:priority
* property.
*
* Returns: the 'priority' property value
*
* Since: 1.30
**/
int
nm_setting_hostname_get_priority(NMSettingHostname *setting)
{
g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), 0);
return setting->priority;
}
/**
* nm_setting_hostname_get_from_dhcp:
* @setting: the #NMSettingHostname
*
* Returns the value contained in the #NMSettingHostname:from-dhcp
* property.
*
* Returns: the 'from-dhcp' property value
*
* Since: 1.30
**/
NMTernary
nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting)
{
g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT);
return setting->from_dhcp;
}
/**
* nm_setting_hostname_get_from_dns_lookup:
* @setting: the #NMSettingHostname
*
* Returns the value contained in the #NMSettingHostname:from-dns-lookup
* property.
*
* Returns: the 'from-dns-lookup' property value
*
* Since: 1.30
**/
NMTernary
nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting)
{
g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT);
return setting->from_dns_lookup;
}
/**
* nm_setting_hostname_get_only_from_default:
* @setting: the #NMSettingHostname
*
* Returns the value contained in the #NMSettingHostname:only-from-default
* property.
*
* Returns: the 'only-from-default' property value
*
* Since: 1.30
**/
NMTernary
nm_setting_hostname_get_only_from_default(NMSettingHostname *setting)
{
g_return_val_if_fail(NM_IS_SETTING_HOSTNAME(setting), NM_TERNARY_DEFAULT);
return setting->only_from_default;
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMSettingHostname *self = NM_SETTING_HOSTNAME(object);
switch (prop_id) {
case PROP_PRIORITY:
g_value_set_int(value, self->priority);
break;
case PROP_FROM_DHCP:
g_value_set_enum(value, self->from_dhcp);
break;
case PROP_FROM_DNS_LOOKUP:
g_value_set_enum(value, self->from_dns_lookup);
break;
case PROP_ONLY_FROM_DEFAULT:
g_value_set_enum(value, self->only_from_default);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NMSettingHostname *self = NM_SETTING_HOSTNAME(object);
switch (prop_id) {
case PROP_PRIORITY:
self->priority = g_value_get_int(value);
break;
case PROP_FROM_DHCP:
self->from_dhcp = g_value_get_enum(value);
break;
case PROP_FROM_DNS_LOOKUP:
self->from_dns_lookup = g_value_get_enum(value);
break;
case PROP_ONLY_FROM_DEFAULT:
self->only_from_default = g_value_get_enum(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_setting_hostname_init(NMSettingHostname *setting)
{
setting->from_dhcp = NM_TERNARY_DEFAULT;
setting->from_dns_lookup = NM_TERNARY_DEFAULT;
setting->only_from_default = NM_TERNARY_DEFAULT;
}
/**
* nm_setting_hostname_new:
*
* Creates a new #NMSettingHostname object with default values.
*
* Returns: (transfer full): the new empty #NMSettingHostname object
*
* Since: 1.30
**/
NMSetting *
nm_setting_hostname_new(void)
{
return g_object_new(NM_TYPE_SETTING_HOSTNAME, NULL);
}
static void
nm_setting_hostname_class_init(NMSettingHostnameClass *klass)
{
GObjectClass * object_class = G_OBJECT_CLASS(klass);
NMSettingClass *setting_class = NM_SETTING_CLASS(klass);
object_class->get_property = get_property;
object_class->set_property = set_property;
/**
* NMSettingHostname:priority
*
* The relative priority of this connection to determine the
* system hostname. A lower numerical value is better (higher
* priority). A connection with higher priority is considered
* before connections with lower priority.
*
* If the value is zero, it can be overridden by a global value
* from NetworkManager configuration. If the property doesn't have
* a value in the global configuration, the value is assumed to be
* 100.
*
* Negative values have the special effect of excluding other
* connections with a greater numerical priority value; so in
* presence of at least one negative priority, only connections
* with the lowest priority value will be used to determine the
* hostname.
*
* Since: 1.30
**/
/* ---ifcfg-rh---
* property: priority
* variable: HOSTNAME_PRIORITY(+)
* default: missing variable means global value or 100
* description: hostname priority
* example: HOSTNAME_PRIORITY=50
* ---end---
*/
obj_properties[PROP_PRIORITY] = g_param_spec_int(NM_SETTING_HOSTNAME_PRIORITY,
"",
"",
G_MININT32,
G_MAXINT32,
0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* NMSettingHostname:from-dhcp
*
* Whether the system hostname can be determined from DHCP on
* this connection.
*
* When set to %NM_TERNARY_DEFAULT, the value from global configuration
* is used. If the property doesn't have a value in the global
* configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE.
*
* Since: 1.30
**/
/* ---ifcfg-rh---
* property: from-dhcp
* variable: HOSTNAME_FROM_DHCP(+)
* default: missing variable means global default or 1
* description: whether the system hostname can be determined from DHCP
* example: HOSTNAME_FROM_DHCP=0,1
* ---end---
*/
obj_properties[PROP_FROM_DHCP] = g_param_spec_enum(
NM_SETTING_HOSTNAME_FROM_DHCP,
"",
"",
NM_TYPE_TERNARY,
NM_TERNARY_DEFAULT,
NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* NMSettingHostname:from-dns-lookup
*
* Whether the system hostname can be determined from reverse
* DNS lookup of addresses on this device.
*
* When set to %NM_TERNARY_DEFAULT, the value from global configuration
* is used. If the property doesn't have a value in the global
* configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE.
*
* Since: 1.30
**/
/* ---ifcfg-rh---
* property: from-dhcp
* variable: HOSTNAME_FROM_DNS_LOOKUP(+)
* default: missing variable means global default or 1
* description: whether the system hostname can be determined from reverse
* DNS lookup
* example: HOSTNAME_FROM_DNS_LOOKUP=0,1
* ---end---
*/
obj_properties[PROP_FROM_DNS_LOOKUP] = g_param_spec_enum(
NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP,
"",
"",
NM_TYPE_TERNARY,
NM_TERNARY_DEFAULT,
NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* NMSettingHostname:only-from-default
*
* If set to %NM_TERNARY_TRUE, NetworkManager attempts to get
* the hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this
* device only when the device has the default route for the given
* address family (IPv4/IPv6).
*
* If set to %NM_TERNARY_FALSE, the hostname can be set from this
* device even if it doesn't have the default route.
*
* When set to %NM_TERNARY_DEFAULT, the value from global configuration
* is used. If the property doesn't have a value in the global
* configuration, NetworkManager assumes the value to be %NM_TERNARY_TRUE.
*
* Since: 1.30
**/
/* ---ifcfg-rh---
* property: only-best-device
* variable: HOSTNAME_ONLY_FROM_DEFAULT(+)
* default: missing variable means global default or 1
* description: whether the hostname can be determined only from
* devices with the default route
* example: HOSTNAME_ONLY_FROM_DEFAULT=0,1
* ---end---
*/
obj_properties[PROP_ONLY_FROM_DEFAULT] = g_param_spec_enum(
NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT,
"",
"",
NM_TYPE_TERNARY,
NM_TERNARY_DEFAULT,
NM_SETTING_PARAM_FUZZY_IGNORE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
_nm_setting_class_commit(setting_class, NM_META_SETTING_TYPE_HOSTNAME);
}

View file

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/*
* Copyright (C) 2020 Red Hat, Inc.
*/
#ifndef NM_SETTING_HOSTNAME_H
#define NM_SETTING_HOSTNAME_H
#if !defined(__NETWORKMANAGER_H_INSIDE__) && !defined(NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include "nm-setting.h"
G_BEGIN_DECLS
#define NM_TYPE_SETTING_HOSTNAME (nm_setting_hostname_get_type())
#define NM_SETTING_HOSTNAME(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostname))
#define NM_SETTING_HOSTNAME_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass))
#define NM_IS_SETTING_HOSTNAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_SETTING_HOSTNAME))
#define NM_IS_SETTING_HOSTNAME_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_SETTING_HOSTNAME))
#define NM_SETTING_HOSTNAME_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_SETTING_HOSTNAME, NMSettingHostnameClass))
#define NM_SETTING_HOSTNAME_SETTING_NAME "hostname"
#define NM_SETTING_HOSTNAME_PRIORITY "priority"
#define NM_SETTING_HOSTNAME_FROM_DHCP "from-dhcp"
#define NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP "from-dns-lookup"
#define NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT "only-from-default"
typedef struct _NMSettingHostnameClass NMSettingHostnameClass;
NM_AVAILABLE_IN_1_30
GType nm_setting_hostname_get_type(void);
NM_AVAILABLE_IN_1_30
NMSetting *nm_setting_hostname_new(void);
NM_AVAILABLE_IN_1_30
int nm_setting_hostname_get_priority(NMSettingHostname *setting);
NM_AVAILABLE_IN_1_30
NMTernary nm_setting_hostname_get_from_dhcp(NMSettingHostname *setting);
NM_AVAILABLE_IN_1_30
NMTernary nm_setting_hostname_get_from_dns_lookup(NMSettingHostname *setting);
NM_AVAILABLE_IN_1_30
NMTernary nm_setting_hostname_get_only_from_default(NMSettingHostname *setting);
G_END_DECLS
#endif /* NM_SETTING_HOSTNAME_H */

View file

@ -62,6 +62,7 @@
#include "nm-setting-ethtool.h"
#include "nm-setting-generic.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-infiniband.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"

View file

@ -1766,6 +1766,11 @@ global:
nm_keyfile_read;
nm_keyfile_warn_severity_get_type;
nm_keyfile_write;
nm_setting_hostname_get_from_dhcp;
nm_setting_hostname_get_from_dns_lookup;
nm_setting_hostname_get_only_from_default;
nm_setting_hostname_get_priority;
nm_setting_hostname_get_type;
nm_setting_ovs_external_ids_check_key;
nm_setting_ovs_external_ids_check_val;
nm_setting_ovs_external_ids_get_data;

View file

@ -1166,7 +1166,7 @@ nml_dbus_object_iface_data_get(NMLDBusObject *dbobj,
count++;
}
} else {
nm_c_list_for_each_entry_prev (db_iface_data, &dbobj->iface_lst_head, iface_lst) {
c_list_for_each_entry_prev (db_iface_data, &dbobj->iface_lst_head, iface_lst) {
if (db_iface_data->dbus_iface_is_wellknown)
break;
if (db_iface_data->iface_removed)

View file

@ -278,18 +278,24 @@ no-auto-default=*
this option. An hostname empty or equal to 'localhost', 'localhost6',
'localhost.localdomain' or 'localhost6.localdomain' is considered invalid.
</para>
<para><literal>default</literal>: NetworkManager will update the hostname
with the one provided via DHCP on the main connection (the one with a default
route). If not present, the hostname will be updated to the last one set
outside NetworkManager. If it is not valid, NetworkManager will try to recover
the hostname from the reverse lookup of the IP address of the main connection.
If this fails too, the hostname will be set to 'localhost.localdomain'.
<para><literal>default</literal>: NetworkManager will update the
hostname with the one provided via DHCP or reverse DNS lookup of the
IP address on the connection with the default route or on any
connection with the property hostname.only-from-default set to
'<literal>false</literal>'. Connections are considered in order of
increasing value of the <literal>hostname.priority</literal>
property. In case multiple connections have the same priority,
connections activated earlier are considered first. If no hostname can
be determined in such way, the hostname will be updated to the last
one set outside NetworkManager or to 'localhost.localdomain'.
</para>
<para><literal>dhcp</literal>: NetworkManager will update the transient hostname
only with information coming from DHCP. No fallback nor reverse lookup will be
performed, but when the dhcp connection providing the hostname is deactivated,
the hostname is reset to the last hostname set outside NetworkManager or
'localhost' if none valid is there.
<para><literal>dhcp</literal>: this is similar to
'<literal>default</literal>', with the difference that after trying to
get the DHCP hostname, reverse DNS lookup is not done. Note that
selecting this option is equivalent to setting the property
'<literal>hostname.from-dns-lookup</literal>' to
'<literal>false</literal>' globally for all connections in
NetworkManager.conf.
</para>
<para><literal>none</literal>: NetworkManager will not manage the transient
hostname and will never set it.
@ -734,6 +740,18 @@ ipv6.ip6-privacy=0
<varlistentry>
<term><varname>gsm.mtu</varname></term>
</varlistentry>
<varlistentry>
<term><varname>hostname.from-dhcp</varname></term>
</varlistentry>
<varlistentry>
<term><varname>hostname.from-dns-lookup</varname></term>
</varlistentry>
<varlistentry>
<term><varname>hostname.only-from-default</varname></term>
</varlistentry>
<varlistentry>
<term><varname>hostname.priority</varname></term>
</varlistentry>
<varlistentry>
<term><varname>infiniband.mtu</varname></term>
<listitem><para>If configured explicitly to 0, the MTU is not reconfigured during device activation unless it is required due to IPv6 constraints. If left unspecified, a DHCP/IPv6 SLAAC provided value is used or the MTU is left unspecified on activation.</para></listitem>

View file

@ -17,11 +17,6 @@
_what &&c_list_contains(list, &_what->member); \
})
/* iterate over the list backwards. */
#define nm_c_list_for_each_entry_prev(_iter, _list, _m) \
for (_iter = c_list_entry((_list)->prev, __typeof__(*_iter), _m); &(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.prev, __typeof__(*_iter), _m))
/*****************************************************************************/
typedef struct {

View file

@ -21,6 +21,7 @@
#include "nm-setting-ethtool.h"
#include "nm-setting-generic.h"
#include "nm-setting-gsm.h"
#include "nm-setting-hostname.h"
#include "nm-setting-infiniband.h"
#include "nm-setting-ip-config.h"
#include "nm-setting-ip-tunnel.h"
@ -243,6 +244,13 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = {
.setting_name = NM_SETTING_GSM_SETTING_NAME,
.get_setting_gtype = nm_setting_gsm_get_type,
},
[NM_META_SETTING_TYPE_HOSTNAME] =
{
.meta_type = NM_META_SETTING_TYPE_HOSTNAME,
.setting_priority = NM_SETTING_PRIORITY_IP,
.setting_name = NM_SETTING_HOSTNAME_SETTING_NAME,
.get_setting_gtype = nm_setting_hostname_get_type,
},
[NM_META_SETTING_TYPE_INFINIBAND] =
{
.meta_type = NM_META_SETTING_TYPE_INFINIBAND,

View file

@ -119,6 +119,7 @@ typedef enum {
NM_META_SETTING_TYPE_ETHTOOL,
NM_META_SETTING_TYPE_GENERIC,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_HOSTNAME,
NM_META_SETTING_TYPE_INFINIBAND,
NM_META_SETTING_TYPE_IP_TUNNEL,
NM_META_SETTING_TYPE_IP4_CONFIG,

View file

@ -42,4 +42,15 @@ c_list_length_is(const CList *list, unsigned long check_len)
return n == check_len;
}
#define c_list_for_each_prev(_iter, _list) \
for (_iter = (_list)->prev; (_iter) != (_list); _iter = (_iter)->prev)
#define c_list_for_each_prev_safe(_iter, _safe, _list) \
for (_iter = (_list)->prev, _safe = (_iter)->prev; (_iter) != (_list); \
_iter = (_safe), _safe = (_safe)->prev)
#define c_list_for_each_entry_prev(_iter, _list, _m) \
for (_iter = c_list_entry((_list)->prev, __typeof__(*_iter), _m); &(_iter)->_m != (_list); \
_iter = c_list_entry((_iter)->_m.prev, __typeof__(*_iter), _m))
#endif /* __C_LIST_UTIL_H__ */

View file

@ -206,6 +206,23 @@ typedef struct {
NMEthtoolRingState * ring;
} 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 {
@ -218,6 +235,7 @@ enum {
REMOVED,
RECHECK_AUTO_ACTIVATE,
RECHECK_ASSUME,
DNS_LOOKUP_DONE,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = {0};
@ -324,6 +342,14 @@ typedef struct _NMDevicePrivate {
int auth_retries;
union {
struct {
HostnameResolver *hostname_resolver_6;
HostnameResolver *hostname_resolver_4;
};
HostnameResolver *hostname_resolver_x[2];
};
union {
const guint8 hw_addr_len; /* read-only */
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
_ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr)
{
@ -15618,6 +15660,7 @@ static void
_cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
guint i;
_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);
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_INET6, cleanup_type);
}
@ -17467,6 +17513,178 @@ nm_device_auth_retries_try_next(NMDevice *self)
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 *
@ -18644,6 +18862,16 @@ nm_device_class_init(NMDeviceClass *klass)
NULL,
G_TYPE_NONE,
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 */

View file

@ -116,6 +116,7 @@ nm_device_state_reason_check(NMDeviceStateReason reason)
#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */
/* Internal signals */
#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done"
#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
#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);
const char *
nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_pending);
#endif /* __NETWORKMANAGER_DEVICE_H__ */

View file

@ -369,6 +369,12 @@ nm_ip_config_hash(const NMIPConfig *self, GChecksum *sum, gboolean dns_only)
_NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_hash, nm_ip6_config_hash, sum, dns_only);
}
static inline gconstpointer
nm_ip_config_get_first_address(NMIPConfig *self)
{
_NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_first_address, nm_ip6_config_get_first_address);
}
static inline void
nm_ip_config_add_address(NMIPConfig *self, const NMPlatformIPAddress *address)
{

View file

@ -142,7 +142,7 @@ typedef struct {
GArray *capabilities;
CList active_connections_lst_head;
CList active_connections_lst_head; /* Oldest ACs at the beginning */
CList async_op_lst_head;
guint ac_cleanup_id;
NMActiveConnection *primary_connection;
@ -941,7 +941,7 @@ active_connection_add(NMManager *self, NMActiveConnection *active)
nm_assert(NM_IS_ACTIVE_CONNECTION(active));
nm_assert(!c_list_is_linked(&active->active_connections_lst));
c_list_link_front(&priv->active_connections_lst_head, &active->active_connections_lst);
c_list_link_tail(&priv->active_connections_lst_head, &active->active_connections_lst);
g_object_ref(active);
g_signal_connect(active,
@ -7867,7 +7867,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
break;
case PROP_ACTIVE_CONNECTIONS:
ptrarr = g_ptr_array_new();
c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) {
c_list_for_each_entry_prev (ac,
&priv->active_connections_lst_head,
active_connections_lst) {
path = nm_dbus_object_get_path(NM_DBUS_OBJECT(ac));
if (path)
g_ptr_array_add(ptrarr, g_strdup(path));

View file

@ -72,6 +72,7 @@ NMState nm_manager_get_state(NMManager *manager);
const CList *nm_manager_get_active_connections(NMManager *manager);
/* From least recently activated */
#define nm_manager_for_each_active_connection(manager, iter, tmp_list) \
for (tmp_list = nm_manager_get_active_connections(manager), \
iter = c_list_entry(tmp_list->next, NMActiveConnection, active_connections_lst); \
@ -86,6 +87,22 @@ const CList *nm_manager_get_active_connections(NMManager *manager);
NMActiveConnection, \
active_connections_lst))
/* From most recently activated */
#define nm_manager_for_each_active_connection_prev(manager, iter, tmp_list) \
for (tmp_list = nm_manager_get_active_connections(manager), \
iter = c_list_entry(tmp_list->prev, NMActiveConnection, active_connections_lst); \
({ \
const gboolean _has_prev = (&iter->active_connections_lst != tmp_list); \
\
if (!_has_prev) \
iter = NULL; \
_has_prev; \
}); \
iter = c_list_entry(iter->active_connections_lst.prev, \
NMActiveConnection, \
active_connections_lst))
/* From least recently activated */
#define nm_manager_for_each_active_connection_safe(manager, iter, tmp_list, iter_safe) \
for (tmp_list = nm_manager_get_active_connections(manager), iter_safe = tmp_list->next; ({ \
if (iter_safe != tmp_list) { \

View file

@ -117,6 +117,8 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv)
/*****************************************************************************/
#define _NMLOG_PREFIX_NAME "policy"
#undef _NMLOG_ENABLED
#define _NMLOG_ENABLED(level, domain) (nm_logging_enabled((level), (domain)))
#define _NMLOG(level, domain, ...) \
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_check(NMPolicy *self, NMDevice *device);
static NMDevice *get_default_device(NMPolicy *self, int addr_family);
@ -354,11 +357,11 @@ device_ip6_prefix_delegated(NMDevice *device, NMPlatformIP6Address *prefix, gpoi
delegation->device = device;
delegation->prefix = *prefix;
/* The newly activated connections are added to the list beginning,
* so traversing it from the beginning makes it likely for newly
/* The newly activated connections are added to the end of the list,
* so traversing it from the end makes it likely for newly
* activated connections that have no subnet assigned to be served
* first. That is a simple yet fair policy, which is good. */
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
nm_manager_for_each_active_connection_prev (priv->manager, ac, tmp_list) {
NMDevice *to_device;
to_device = nm_active_connection_get_device(ac);
@ -671,20 +674,168 @@ lookup_by_address(NMPolicy *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
update_system_hostname(NMPolicy *self, const char *msg)
{
NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
const char * configured_hostname;
gs_free char * temp_hostname = NULL;
const char * dhcp_hostname, *p;
NMIP4Config * ip4_config;
NMIP6Config * ip6_config;
gboolean external_hostname = FALSE;
const NMPlatformIP4Address *addr4;
const NMPlatformIP6Address *addr6;
NMDevice * device;
NMDhcpConfig * dhcp_config;
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
const char * configured_hostname;
gs_free char * temp_hostname = NULL;
const char * dhcp_hostname, *p;
gboolean external_hostname = FALSE;
NMDhcpConfig * dhcp_config;
gs_unref_array GArray *infos = NULL;
DeviceHostnameInfo * info;
guint i;
int IS_IPv4;
g_return_if_fail(self != NULL);
@ -724,10 +875,9 @@ update_system_hostname(NMPolicy *self, const char *msg)
/* Hostname precedence order:
*
* 1) a configured hostname (from settings)
* 2) automatic hostname from the default device's config (DHCP, VPN, etc)
* 3) the last hostname set outside NM
* 4) reverse-DNS of the best device's IPv4 address
*
* 2) automatic hostname from DHCP of eligible interfaces
* 3) reverse-DNS lookup of the first address on eligible interfaces
* 4) the last hostname set outside NM
*/
/* Try a persistent hostname first */
@ -738,40 +888,73 @@ update_system_hostname(NMPolicy *self, const char *msg)
return;
}
if (priv->default_ac4) {
/* 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 (dhcp_config) {
dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "host_name");
if (dhcp_hostname && dhcp_hostname[0]) {
p = nm_str_skip_leading_spaces(dhcp_hostname);
if (p[0]) {
_set_hostname(self, p, "from DHCPv4");
priv->dhcp_hostname = TRUE;
return;
}
_LOGW(LOGD_DNS,
"set-hostname: DHCPv4-provided hostname '%s' looks invalid; ignoring it",
dhcp_hostname);
}
infos = build_device_hostname_infos(self);
if (infos && _LOGT_ENABLED(LOGD_DNS)) {
_LOGT(LOGD_DNS, "device hostname info:");
for (i = 0; i < infos->len; i++) {
info = &g_array_index(infos, DeviceHostnameInfo, i);
_LOGT(LOGD_DNS,
" - prio:%4d ipv:%c%c dhcp:%d dns:%d dev:%s",
info->priority,
info->ip_4 ? '4' : '-',
info->ip_6 ? '6' : '-',
info->from_dhcp,
info->from_dns,
nm_device_get_iface(info->device));
}
}
if (priv->default_ac6) {
/* Grab a hostname out of the device's DHCP6 config */
dhcp_config = nm_device_get_dhcp_config(get_default_device(self, AF_INET6), AF_INET6);
if (dhcp_config) {
dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "fqdn_fqdn");
if (dhcp_hostname && dhcp_hostname[0]) {
p = nm_str_skip_leading_spaces(dhcp_hostname);
if (p[0]) {
_set_hostname(self, p, "from DHCPv6");
priv->dhcp_hostname = TRUE;
return;
for (i = 0; infos && i < infos->len; i++) {
info = &g_array_index(infos, DeviceHostnameInfo, i);
g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self);
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
if (info->from_dhcp && info->ip_x[IS_IPv4]) {
dhcp_config = nm_device_get_dhcp_config(info->device, addr_family);
if (dhcp_config) {
dhcp_hostname =
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;
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
* set externally to NM
*/
@ -811,30 +986,7 @@ update_system_hostname(NMPolicy *self, const char *msg)
return;
}
/* No configured hostname, no automatically determined hostname, and no
* 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);
_set_hostname(self, NULL, "no hostname found");
}
static void
@ -1796,6 +1948,8 @@ device_state_changed(NMDevice * device,
switch (new_state) {
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
* 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);
break;
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
* was unplugged and plugged in again, we should try to reconnect.
*/

View file

@ -2546,6 +2546,42 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea
return NM_SETTING(g_steal_pointer(&s_ip6));
}
static NMSetting *
make_hostname_setting(shvarFile *ifcfg)
{
NMSetting *setting;
NMTernary from_dhcp;
NMTernary from_dns_lookup;
NMTernary only_from_default;
int priority;
priority = svGetValueInt64(ifcfg, "HOSTNAME_PRIORITY", 10, G_MININT32, G_MAXINT32, 0);
from_dhcp = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DHCP");
from_dns_lookup = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP");
only_from_default = svGetValueTernary(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT");
/* Create the setting when at least one key is not default*/
if (priority == 0 && from_dhcp == NM_TERNARY_DEFAULT && from_dns_lookup == NM_TERNARY_DEFAULT
&& only_from_default == NM_TERNARY_DEFAULT)
return NULL;
setting = nm_setting_hostname_new();
g_object_set(setting,
NM_SETTING_HOSTNAME_PRIORITY,
priority,
NM_SETTING_HOSTNAME_FROM_DHCP,
from_dhcp,
NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP,
from_dns_lookup,
NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT,
only_from_default,
NULL);
return setting;
}
static NMSetting *
make_sriov_setting(shvarFile *ifcfg)
{
@ -2951,7 +2987,8 @@ make_dcb_setting(shvarFile *ifcfg, NMSetting **out_setting, GError **error)
gboolean dcb_on;
NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
g_return_val_if_fail(out_setting != NULL, FALSE);
g_return_val_if_fail(out_setting, FALSE);
*out_setting = NULL;
dcb_on = !!svGetValueBoolean(ifcfg, "DCB", FALSE);
if (!dcb_on)
@ -6243,8 +6280,9 @@ connection_from_file_full(const char *filename,
gs_unref_object NMConnection *connection = NULL;
gs_free char * type = NULL;
char * devtype, *bootproto;
NMSetting * s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user;
NMSetting * s_sriov, *s_match;
NMSetting * setting;
NMSetting * s_ip4;
NMSetting * s_ip6;
const char * ifcfg_name = NULL;
gboolean has_ip4_defroute = FALSE;
gboolean has_complex_routes_v4;
@ -6532,13 +6570,13 @@ connection_from_file_full(const char *filename,
NM_SETTING_IP_CONFIG(s_ip4),
NM_SETTING_IP_CONFIG(s_ip6));
s_sriov = make_sriov_setting(main_ifcfg);
if (s_sriov)
nm_connection_add_setting(connection, s_sriov);
setting = make_sriov_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
s_tc = make_tc_setting(main_ifcfg);
if (s_tc)
nm_connection_add_setting(connection, s_tc);
setting = make_tc_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
/* For backwards compatibility, if IPv4 is disabled or the
* config fails for some reason, we read DOMAIN and put the
@ -6546,30 +6584,34 @@ connection_from_file_full(const char *filename,
*/
check_dns_search_domains(main_ifcfg, s_ip4, s_ip6);
s_proxy = make_proxy_setting(main_ifcfg);
if (s_proxy)
nm_connection_add_setting(connection, s_proxy);
setting = make_proxy_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
s_user = make_user_setting(main_ifcfg);
if (s_user)
nm_connection_add_setting(connection, s_user);
setting = make_hostname_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
s_match = make_match_setting(main_ifcfg);
if (s_match)
nm_connection_add_setting(connection, s_match);
setting = make_user_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
s_port = make_bridge_port_setting(main_ifcfg);
if (s_port)
nm_connection_add_setting(connection, s_port);
setting = make_match_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
s_port = make_team_port_setting(main_ifcfg);
if (s_port)
nm_connection_add_setting(connection, s_port);
setting = make_bridge_port_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
if (!make_dcb_setting(main_ifcfg, &s_dcb, error))
setting = make_team_port_setting(main_ifcfg);
if (setting)
nm_connection_add_setting(connection, setting);
if (!make_dcb_setting(main_ifcfg, &setting, error))
return NULL;
if (s_dcb)
nm_connection_add_setting(connection, s_dcb);
if (setting)
nm_connection_add_setting(connection, setting);
if (!nm_connection_normalize(connection, NULL, NULL, error))
return NULL;

View file

@ -873,6 +873,10 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = {
_KEY_TYPE("GATEWAY_PING_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("GENERATE_MAC_ADDRESS_MASK", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("GVRP", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HOSTNAME_FROM_DHCP", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HOSTNAME_FROM_DNS_LOOKUP", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HOSTNAME_ONLY_FROM_DEFAULT", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HOSTNAME_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HWADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("HWADDR_BLACKLIST", NMS_IFCFG_KEY_TYPE_IS_PLAIN),
_KEY_TYPE("IEEE_8021X_ALTSUBJECT_MATCHES", NMS_IFCFG_KEY_TYPE_IS_PLAIN),

View file

@ -33,7 +33,7 @@ typedef struct {
NMSIfcfgKeyTypeFlags key_flags;
} NMSIfcfgKeyTypeInfo;
extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[243];
extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[247];
const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx);

View file

@ -1051,6 +1051,28 @@ write_infiniband_setting(NMConnection *connection, shvarFile *ifcfg, GError **er
return TRUE;
}
static void
write_hostname_setting(NMConnection *connection, shvarFile *ifcfg)
{
NMSettingHostname *s_hostname;
NMTernary t;
s_hostname = _nm_connection_get_setting(connection, NM_TYPE_SETTING_HOSTNAME);
if (!s_hostname)
return;
svSetValueInt64(ifcfg, "HOSTNAME_PRIORITY", nm_setting_hostname_get_priority(s_hostname));
t = nm_setting_hostname_get_from_dhcp(s_hostname);
svSetValueInt64_cond(ifcfg, "HOSTNAME_FROM_DHCP", t != NM_TERNARY_DEFAULT, t);
t = nm_setting_hostname_get_from_dns_lookup(s_hostname);
svSetValueInt64_cond(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP", t != NM_TERNARY_DEFAULT, t);
t = nm_setting_hostname_get_only_from_default(s_hostname);
svSetValueInt64_cond(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT", t != NM_TERNARY_DEFAULT, t);
}
static gboolean
write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error)
{
@ -3347,7 +3369,7 @@ do_write_construct(NMConnection * connection,
return FALSE;
write_match_setting(connection, ifcfg);
write_hostname_setting(connection, ifcfg);
write_sriov_setting(connection, ifcfg);
if (!write_tc_setting(connection, ifcfg, error))