Thomas Haller 2016-06-30 08:36:58 +02:00
commit 9a354cdc90
61 changed files with 2770 additions and 755 deletions

View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <arpa/inet.h>
#include "nm-common-macros.h"
#include "utils.h"
#include "common.h"
#include "nm-vpn-helpers.h"
@ -44,26 +45,28 @@ NmcOutputField nmc_fields_setting_connection[] = {
SETTING_FIELD ("name"), /* 0 */
SETTING_FIELD (NM_SETTING_CONNECTION_ID), /* 1 */
SETTING_FIELD (NM_SETTING_CONNECTION_UUID), /* 2 */
SETTING_FIELD (NM_SETTING_CONNECTION_INTERFACE_NAME), /* 3 */
SETTING_FIELD (NM_SETTING_CONNECTION_TYPE), /* 4 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT), /* 5 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY), /* 6 */
SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP), /* 7 */
SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY), /* 8 */
SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS), /* 9 */
SETTING_FIELD (NM_SETTING_CONNECTION_ZONE), /* 10 */
SETTING_FIELD (NM_SETTING_CONNECTION_MASTER), /* 11 */
SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE), /* 12 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES), /* 13 */
SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES), /* 14 */
SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT), /* 15 */
SETTING_FIELD (NM_SETTING_CONNECTION_METERED), /* 16 */
SETTING_FIELD (NM_SETTING_CONNECTION_LLDP), /* 17 */
SETTING_FIELD (NM_SETTING_CONNECTION_STABLE_ID), /* 3 */
SETTING_FIELD (NM_SETTING_CONNECTION_INTERFACE_NAME), /* 4 */
SETTING_FIELD (NM_SETTING_CONNECTION_TYPE), /* 5 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT), /* 6 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY), /* 7 */
SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP), /* 8 */
SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY), /* 9 */
SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS), /* 10 */
SETTING_FIELD (NM_SETTING_CONNECTION_ZONE), /* 11 */
SETTING_FIELD (NM_SETTING_CONNECTION_MASTER), /* 12 */
SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE), /* 13 */
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES), /* 14 */
SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES), /* 15 */
SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT), /* 16 */
SETTING_FIELD (NM_SETTING_CONNECTION_METERED), /* 17 */
SETTING_FIELD (NM_SETTING_CONNECTION_LLDP), /* 18 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_CONNECTION_ALL "name"","\
NM_SETTING_CONNECTION_ID","\
NM_SETTING_CONNECTION_UUID","\
NM_SETTING_CONNECTION_STABLE_ID","\
NM_SETTING_CONNECTION_INTERFACE_NAME","\
NM_SETTING_CONNECTION_TYPE","\
NM_SETTING_CONNECTION_AUTOCONNECT","\
@ -89,13 +92,14 @@ NmcOutputField nmc_fields_setting_wired[] = {
SETTING_FIELD (NM_SETTING_WIRED_AUTO_NEGOTIATE), /* 4 */
SETTING_FIELD (NM_SETTING_WIRED_MAC_ADDRESS), /* 5 */
SETTING_FIELD (NM_SETTING_WIRED_CLONED_MAC_ADDRESS), /* 6 */
SETTING_FIELD (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST), /* 7 */
SETTING_FIELD (NM_SETTING_WIRED_MTU), /* 8 */
SETTING_FIELD (NM_SETTING_WIRED_S390_SUBCHANNELS), /* 9 */
SETTING_FIELD (NM_SETTING_WIRED_S390_NETTYPE), /* 10 */
SETTING_FIELD (NM_SETTING_WIRED_S390_OPTIONS), /* 11 */
SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN), /* 12 */
SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD), /* 13 */
SETTING_FIELD (NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK), /* 7 */
SETTING_FIELD (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST), /* 8 */
SETTING_FIELD (NM_SETTING_WIRED_MTU), /* 9 */
SETTING_FIELD (NM_SETTING_WIRED_S390_SUBCHANNELS), /* 10 */
SETTING_FIELD (NM_SETTING_WIRED_S390_NETTYPE), /* 11 */
SETTING_FIELD (NM_SETTING_WIRED_S390_OPTIONS), /* 12 */
SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN), /* 13 */
SETTING_FIELD (NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD), /* 14 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_WIRED_ALL "name"","\
@ -105,6 +109,7 @@ NmcOutputField nmc_fields_setting_wired[] = {
NM_SETTING_WIRED_AUTO_NEGOTIATE","\
NM_SETTING_WIRED_MAC_ADDRESS","\
NM_SETTING_WIRED_CLONED_MAC_ADDRESS","\
NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK","\
NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST","\
NM_SETTING_WIRED_MTU","\
NM_SETTING_WIRED_S390_SUBCHANNELS","\
@ -200,12 +205,13 @@ NmcOutputField nmc_fields_setting_wireless[] = {
SETTING_FIELD (NM_SETTING_WIRELESS_TX_POWER), /* 7 */
SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS), /* 8 */
SETTING_FIELD (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS), /* 9 */
SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST), /* 10 */
SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION), /* 11 */
SETTING_FIELD (NM_SETTING_WIRELESS_MTU), /* 12 */
SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS), /* 13 */
SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN), /* 14 */
SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE), /* 15 */
SETTING_FIELD (NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK), /* 10 */
SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST), /* 11 */
SETTING_FIELD (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION), /* 12 */
SETTING_FIELD (NM_SETTING_WIRELESS_MTU), /* 13 */
SETTING_FIELD (NM_SETTING_WIRELESS_SEEN_BSSIDS), /* 14 */
SETTING_FIELD (NM_SETTING_WIRELESS_HIDDEN), /* 15 */
SETTING_FIELD (NM_SETTING_WIRELESS_POWERSAVE), /* 16 */
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
};
#define NMC_FIELDS_SETTING_WIRELESS_ALL "name"","\
@ -218,6 +224,7 @@ NmcOutputField nmc_fields_setting_wireless[] = {
NM_SETTING_WIRELESS_TX_POWER","\
NM_SETTING_WIRELESS_MAC_ADDRESS","\
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS","\
NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK","\
NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST","\
NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION","\
NM_SETTING_WIRELESS_MTU","\
@ -1252,6 +1259,7 @@ DEFINE_SECRET_FLAGS_GETTER (nmc_property_cdma_get_password_flags, NM_SETTING_CDM
/* --- NM_SETTING_CONNECTION_SETTING_NAME property get functions --- */
DEFINE_GETTER (nmc_property_connection_get_id, NM_SETTING_CONNECTION_ID)
DEFINE_GETTER (nmc_property_connection_get_uuid, NM_SETTING_CONNECTION_UUID)
DEFINE_GETTER (nmc_property_connection_get_stable_id, NM_SETTING_CONNECTION_STABLE_ID)
DEFINE_GETTER (nmc_property_connection_get_interface_name, NM_SETTING_CONNECTION_INTERFACE_NAME)
DEFINE_GETTER (nmc_property_connection_get_type, NM_SETTING_CONNECTION_TYPE)
DEFINE_GETTER (nmc_property_connection_get_autoconnect, NM_SETTING_CONNECTION_AUTOCONNECT)
@ -1761,6 +1769,7 @@ DEFINE_GETTER (nmc_property_wired_get_duplex, NM_SETTING_WIRED_DUPLEX)
DEFINE_GETTER (nmc_property_wired_get_auto_negotiate, NM_SETTING_WIRED_AUTO_NEGOTIATE)
DEFINE_GETTER (nmc_property_wired_get_mac_address, NM_SETTING_WIRED_MAC_ADDRESS)
DEFINE_GETTER (nmc_property_wired_get_cloned_mac_address, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)
DEFINE_GETTER (nmc_property_wired_get_generate_mac_address_mask, NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK)
DEFINE_GETTER (nmc_property_wired_get_mac_address_blacklist, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST)
DEFINE_GETTER (nmc_property_wired_get_s390_subchannels, NM_SETTING_WIRED_S390_SUBCHANNELS)
DEFINE_GETTER (nmc_property_wired_get_s390_nettype, NM_SETTING_WIRED_S390_NETTYPE)
@ -1887,6 +1896,7 @@ DEFINE_GETTER (nmc_property_wireless_get_rate, NM_SETTING_WIRELESS_RATE)
DEFINE_GETTER (nmc_property_wireless_get_tx_power, NM_SETTING_WIRELESS_TX_POWER)
DEFINE_GETTER (nmc_property_wireless_get_mac_address, NM_SETTING_WIRELESS_MAC_ADDRESS)
DEFINE_GETTER (nmc_property_wireless_get_cloned_mac_address, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)
DEFINE_GETTER (nmc_property_wireless_get_generate_mac_address_mask, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK)
DEFINE_GETTER (nmc_property_wireless_get_mac_address_blacklist, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST)
DEFINE_GETTER (nmc_property_wireless_get_seen_bssids, NM_SETTING_WIRELESS_SEEN_BSSIDS)
DEFINE_GETTER (nmc_property_wireless_get_hidden, NM_SETTING_WIRELESS_HIDDEN)
@ -2886,11 +2896,12 @@ nmc_property_set_ssid (NMSetting *setting, const char *prop, const char *val, GE
}
static gboolean
nmc_property_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
_property_set_mac (NMSetting *setting, const char *prop, const char *val, gboolean cloned_mac_addr, GError **error)
{
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!nm_utils_hwaddr_valid (val, ETH_ALEN)) {
if ( (!cloned_mac_addr || !NM_CLONED_MAC_IS_SPECIAL (val))
&& !nm_utils_hwaddr_valid (val, ETH_ALEN)) {
g_set_error (error, 1, 0, _("'%s' is not a valid Ethernet MAC"), val);
return FALSE;
}
@ -2899,6 +2910,18 @@ nmc_property_set_mac (NMSetting *setting, const char *prop, const char *val, GEr
return TRUE;
}
static gboolean
nmc_property_set_mac (NMSetting *setting, const char *prop, const char *val, GError **error)
{
return _property_set_mac (setting, prop, val, FALSE, error);
}
static gboolean
nmc_property_set_mac_cloned (NMSetting *setting, const char *prop, const char *val, GError **error)
{
return _property_set_mac (setting, prop, val, TRUE, error);
}
static gboolean
nmc_property_set_mtu (NMSetting *setting, const char *prop, const char *val, GError **error)
{
@ -6217,6 +6240,13 @@ nmc_properties_init (void)
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (CONNECTION, STABLE_ID),
nmc_property_connection_get_stable_id,
nmc_property_set_string,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (CONNECTION, INTERFACE_NAME),
nmc_property_connection_get_interface_name,
nmc_property_set_ifname,
@ -7188,7 +7218,14 @@ nmc_properties_init (void)
NULL);
nmc_add_prop_funcs (GLUE (WIRED, CLONED_MAC_ADDRESS),
nmc_property_wired_get_cloned_mac_address,
nmc_property_set_mac,
nmc_property_set_mac_cloned,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (WIRED, GENERATE_MAC_ADDRESS_MASK),
nmc_property_wired_get_generate_mac_address_mask,
nmc_property_set_string,
NULL,
NULL,
NULL,
@ -7306,7 +7343,14 @@ nmc_properties_init (void)
NULL);
nmc_add_prop_funcs (GLUE (WIRELESS, CLONED_MAC_ADDRESS),
nmc_property_wireless_get_cloned_mac_address,
nmc_property_set_mac,
nmc_property_set_mac_cloned,
NULL,
NULL,
NULL,
NULL);
nmc_add_prop_funcs (GLUE (WIRELESS, GENERATE_MAC_ADDRESS_MASK),
nmc_property_wireless_get_generate_mac_address_mask,
nmc_property_set_string,
NULL,
NULL,
NULL,
@ -8063,21 +8107,22 @@ setting_connection_details (NMSetting *setting, NmCli *nmc, const char *one_pro
set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting)));
set_val_str (arr, 1, nmc_property_connection_get_id (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 2, nmc_property_connection_get_uuid (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 3, nmc_property_connection_get_interface_name (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 4, nmc_property_connection_get_type (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 5, nmc_property_connection_get_autoconnect (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 6, nmc_property_connection_get_autoconnect_priority (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 7, nmc_property_connection_get_timestamp (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 8, nmc_property_connection_get_read_only (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 9, nmc_property_connection_get_permissions (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_connection_get_zone (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_connection_get_master (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_connection_get_slave_type (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_connection_get_autoconnect_slaves (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 14, nmc_property_connection_get_secondaries (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 15, nmc_property_connection_get_gateway_ping_timeout (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 16, nmc_property_connection_get_metered (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 17, nmc_property_connection_get_lldp (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 3, nmc_property_connection_get_stable_id (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 4, nmc_property_connection_get_interface_name (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 5, nmc_property_connection_get_type (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 6, nmc_property_connection_get_autoconnect (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 7, nmc_property_connection_get_autoconnect_priority (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 8, nmc_property_connection_get_timestamp (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 9, nmc_property_connection_get_read_only (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_connection_get_permissions (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_connection_get_zone (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_connection_get_master (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_connection_get_slave_type (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 14, nmc_property_connection_get_autoconnect_slaves (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 15, nmc_property_connection_get_secondaries (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 16, nmc_property_connection_get_gateway_ping_timeout (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 17, nmc_property_connection_get_metered (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 18, nmc_property_connection_get_lldp (setting, NMC_PROPERTY_GET_PRETTY));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */
@ -8109,13 +8154,14 @@ setting_wired_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gb
set_val_str (arr, 4, nmc_property_wired_get_auto_negotiate (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 5, nmc_property_wired_get_mac_address (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 6, nmc_property_wired_get_cloned_mac_address (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 7, nmc_property_wired_get_mac_address_blacklist (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 8, nmc_property_wired_get_mtu (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 9, nmc_property_wired_get_s390_subchannels (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_wired_get_s390_nettype (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_wired_get_s390_options (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_wired_get_wake_on_lan (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_wired_get_wake_on_lan_password (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 7, nmc_property_wired_get_generate_mac_address_mask (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 8, nmc_property_wired_get_mac_address_blacklist (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 9, nmc_property_wired_get_mtu (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_wired_get_s390_subchannels (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_wired_get_s390_nettype (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_wired_get_s390_options (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_wired_get_wake_on_lan (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 14, nmc_property_wired_get_wake_on_lan_password (setting, NMC_PROPERTY_GET_PRETTY));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */
@ -8209,12 +8255,13 @@ setting_wireless_details (NMSetting *setting, NmCli *nmc, const char *one_prop,
set_val_str (arr, 7, nmc_property_wireless_get_tx_power (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 8, nmc_property_wireless_get_mac_address (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 9, nmc_property_wireless_get_cloned_mac_address (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_wireless_get_mac_address_blacklist (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_wireless_get_mac_address_randomization (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_wireless_get_mtu (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_wireless_get_seen_bssids (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 14, nmc_property_wireless_get_hidden (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 15, nmc_property_wireless_get_powersave (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 10, nmc_property_wireless_get_generate_mac_address_mask (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 11, nmc_property_wireless_get_mac_address_blacklist (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 12, nmc_property_wireless_get_mac_address_randomization (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 13, nmc_property_wireless_get_mtu (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 14, nmc_property_wireless_get_seen_bssids (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 15, nmc_property_wireless_get_hidden (setting, NMC_PROPERTY_GET_PRETTY));
set_val_str (arr, 16, nmc_property_wireless_get_powersave (setting, NMC_PROPERTY_GET_PRETTY));
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */

View File

@ -28,11 +28,13 @@
#include "nm-default.h"
#include "nmt-mac-entry.h"
#include <string.h>
#include "NetworkManager.h"
#include "nm-common-macros.h"
#include "nmt-mac-entry.h"
G_DEFINE_TYPE (NmtMacEntry, nmt_mac_entry, NMT_TYPE_NEWT_ENTRY)
@ -41,6 +43,7 @@ G_DEFINE_TYPE (NmtMacEntry, nmt_mac_entry, NMT_TYPE_NEWT_ENTRY)
typedef struct {
int mac_length;
int mac_str_length;
NmtMacEntryType entry_type;
} NmtMacEntryPrivate;
@ -48,6 +51,7 @@ enum {
PROP_0,
PROP_MAC_LENGTH,
PROP_MAC_ADDRESS,
PROP_ENTRY_TYPE,
LAST_PROP
};
@ -57,6 +61,7 @@ enum {
* @width: the width in characters of the entry
* @mac_length: the length in bytes of the hardware address
* (either %ETH_ALEN or %INFINIBAND_ALEN)
* @entry_type: the type of the entry.
*
* Creates a new #NmtMacEntry.
*
@ -64,11 +69,13 @@ enum {
*/
NmtNewtWidget *
nmt_mac_entry_new (int width,
int mac_length)
int mac_length,
NmtMacEntryType entry_type)
{
return g_object_new (NMT_TYPE_MAC_ENTRY,
"width", width,
"mac-length", mac_length,
"entry-type", (int) entry_type,
NULL);
}
@ -81,6 +88,9 @@ mac_filter (NmtNewtEntry *entry,
{
NmtMacEntryPrivate *priv = NMT_MAC_ENTRY_GET_PRIVATE (entry);
if (priv->entry_type != NMT_MAC_ENTRY_TYPE_MAC)
return TRUE;
if (position >= priv->mac_str_length)
return FALSE;
@ -98,6 +108,11 @@ mac_validator (NmtNewtEntry *entry,
if (!*text)
return TRUE;
if (priv->entry_type == NMT_MAC_ENTRY_TYPE_CLONED) {
if (NM_CLONED_MAC_IS_SPECIAL (text))
return TRUE;
}
p = text;
while ( g_ascii_isxdigit (p[0])
&& g_ascii_isxdigit (p[1])
@ -112,7 +127,9 @@ mac_validator (NmtNewtEntry *entry,
if (!*p)
return (p - text == priv->mac_str_length);
if (g_ascii_isxdigit (p[0]) && !p[1]) {
if ( g_ascii_isxdigit (p[0])
&& !p[1]
&& p - text < priv->mac_str_length) {
char *fixed = g_strdup_printf ("%.*s:%c", (int)(p - text), text, *p);
nmt_newt_entry_set_text (entry, fixed);
@ -161,6 +178,10 @@ nmt_mac_entry_set_property (GObject *object,
case PROP_MAC_ADDRESS:
nmt_newt_entry_set_text (NMT_NEWT_ENTRY (object), g_value_get_string (value));
break;
case PROP_ENTRY_TYPE:
/* construct-only */
priv->entry_type = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -182,6 +203,9 @@ nmt_mac_entry_get_property (GObject *object,
case PROP_MAC_ADDRESS:
g_value_set_string (value, nmt_newt_entry_get_text (NMT_NEWT_ENTRY (object)));
break;
case PROP_ENTRY_TYPE:
g_value_set_int (value, priv->entry_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -224,4 +248,17 @@ nmt_mac_entry_class_init (NmtMacEntryClass *entry_class)
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/**
* NmtMacEntry:entry-type:
*
* The type of the #NmtMacEntry. Can be either used for plain
* MAC addresses or for the extended format for cloned MAC addresses.
*/
g_object_class_install_property
(object_class, PROP_ENTRY_TYPE,
g_param_spec_int ("entry-type", "", "",
NMT_MAC_ENTRY_TYPE_MAC, NMT_MAC_ENTRY_TYPE_CLONED, NMT_MAC_ENTRY_TYPE_MAC,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}

View File

@ -25,6 +25,11 @@
G_BEGIN_DECLS
typedef enum { /*< skip >*/
NMT_MAC_ENTRY_TYPE_MAC,
NMT_MAC_ENTRY_TYPE_CLONED,
} NmtMacEntryType;
#define NMT_TYPE_MAC_ENTRY (nmt_mac_entry_get_type ())
#define NMT_MAC_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMT_TYPE_MAC_ENTRY, NmtMacEntry))
#define NMT_MAC_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMT_TYPE_MAC_ENTRY, NmtMacEntryClass))
@ -45,7 +50,8 @@ typedef struct {
GType nmt_mac_entry_get_type (void);
NmtNewtWidget *nmt_mac_entry_new (int width,
int mac_length);
int mac_length,
NmtMacEntryType type);
G_END_DECLS

View File

@ -70,7 +70,7 @@ nmt_page_ethernet_constructed (GObject *object)
section = nmt_editor_section_new (_("ETHERNET"), NULL, FALSE);
grid = nmt_editor_section_get_body (section);
widget = nmt_mac_entry_new (40, ETH_ALEN);
widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
g_object_bind_property (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget, "mac-address",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

View File

@ -115,7 +115,7 @@ nmt_page_vlan_constructed (GObject *object)
nmt_editor_grid_append (grid, NULL, nmt_newt_separator_new (), NULL);
widget = nmt_mac_entry_new (40, ETH_ALEN);
widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
g_object_bind_property (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
widget, "mac-address",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

View File

@ -351,13 +351,13 @@ nmt_page_wifi_constructed (GObject *object)
nmt_editor_grid_append (grid, NULL, nmt_newt_separator_new (), NULL);
widget = nmt_mac_entry_new (40, ETH_ALEN);
widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_MAC);
g_object_bind_property (s_wireless, NM_SETTING_WIRELESS_BSSID,
widget, "mac-address",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
nmt_editor_grid_append (grid, _("BSSID"), widget, NULL);
widget = nmt_mac_entry_new (40, ETH_ALEN);
widget = nmt_mac_entry_new (40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED);
g_object_bind_property (s_wireless, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
widget, "mac-address",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

View File

@ -847,6 +847,52 @@ _normalize_bond_mode (NMConnection *self, GHashTable *parameters)
return FALSE;
}
static gboolean
_normalize_wireless_mac_address_randomization (NMConnection *self, GHashTable *parameters)
{
NMSettingWireless *s_wifi = nm_connection_get_setting_wireless (self);
const char *cloned_mac_address;
NMSettingMacRandomization mac_address_randomization;
if (!s_wifi)
return FALSE;
mac_address_randomization = nm_setting_wireless_get_mac_address_randomization (s_wifi);
if (!NM_IN_SET (mac_address_randomization,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
NM_SETTING_MAC_RANDOMIZATION_NEVER,
NM_SETTING_MAC_RANDOMIZATION_ALWAYS))
return FALSE;
cloned_mac_address = nm_setting_wireless_get_cloned_mac_address (s_wifi);
if (cloned_mac_address) {
if (nm_streq (cloned_mac_address, "random")) {
if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
return FALSE;
mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_ALWAYS;
} else if (nm_streq (cloned_mac_address, "permanent")) {
if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER)
return FALSE;
mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER;
} else {
if (mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT)
return FALSE;
mac_address_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT;
}
g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, mac_address_randomization, NULL);
return TRUE;
}
if (mac_address_randomization != NM_SETTING_MAC_RANDOMIZATION_DEFAULT) {
g_object_set (s_wifi,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS
? "random" : "permanent",
NULL);
return TRUE;
}
return FALSE;
}
/**
* nm_connection_verify:
* @connection: the #NMConnection to verify
@ -1089,6 +1135,7 @@ nm_connection_normalize (NMConnection *connection,
was_modified |= _normalize_ip_config (connection, parameters);
was_modified |= _normalize_infiniband_mtu (connection, parameters);
was_modified |= _normalize_bond_mode (connection, parameters);
was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters);
/* Verify anew. */
success = _nm_connection_verify (connection, error);

View File

@ -124,6 +124,8 @@ guint32 _nm_setting_get_setting_priority (NMSetting *setting);
gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value);
guint _nm_utils_hwaddr_length (const char *asc);
GSList * _nm_utils_hash_values_to_slist (GHashTable *hash);
GHashTable *_nm_utils_copy_strdict (GHashTable *strdict);
@ -281,6 +283,16 @@ void _nm_setting_vlan_get_priorities (NMSettingVlan *setting,
/***********************************************************/
struct ether_addr;
gboolean _nm_utils_generate_mac_address_mask_parse (const char *value,
struct ether_addr *out_mask,
struct ether_addr **out_ouis,
gsize *out_ouis_len,
GError **error);
/***********************************************************/
typedef enum {
NM_BOND_OPTION_TYPE_INT,
NM_BOND_OPTION_TYPE_STRING,

View File

@ -31,6 +31,7 @@
#include <arpa/inet.h>
#include <string.h>
#include "nm-common-macros.h"
#include "nm-core-internal.h"
#include "nm-keyfile-utils.h"
@ -581,19 +582,28 @@ ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const cha
}
static void
mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key, gsize enforce_length)
mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key, gsize enforce_length, gboolean cloned_mac_addr)
{
const char *setting_name = nm_setting_get_name (setting);
char *tmp_string = NULL, *p, *mac_str;
gint *tmp_list;
GByteArray *array = NULL;
gs_free char *tmp_string = NULL;
const char *p, *mac_str;
gs_free guint8 *buf_arr = NULL;
guint buf_len;
gsize length;
p = tmp_string = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL);
tmp_string = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL);
if ( cloned_mac_addr
&& NM_CLONED_MAC_IS_SPECIAL (tmp_string)) {
mac_str = tmp_string;
goto out;
}
if (tmp_string && tmp_string[0]) {
/* Look for enough ':' characters to signify a MAC address */
guint i = 0;
p = tmp_string;
while (*p) {
if (*p == ':')
i++;
@ -602,23 +612,24 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
if (enforce_length == 0 || enforce_length == i+1) {
/* If we found enough it's probably a string-format MAC address */
array = g_byte_array_sized_new (i+1);
g_byte_array_set_size (array, i+1);
if (!nm_utils_hwaddr_aton (tmp_string, array->data, array->len)) {
g_byte_array_unref (array);
array = NULL;
}
buf_len = i + 1;
buf_arr = g_new (guint8, buf_len);
if (!nm_utils_hwaddr_aton (tmp_string, buf_arr, buf_len))
g_clear_pointer (&buf_arr, g_free);
}
}
g_free (tmp_string);
g_clear_pointer (&tmp_string, g_free);
if (!buf_arr) {
gs_free int *tmp_list = NULL;
if (array == NULL) {
/* Old format; list of ints */
tmp_list = nm_keyfile_plugin_kf_get_integer_list (info->keyfile, setting_name, key, &length, NULL);
if (length > 0 && (enforce_length == 0 || enforce_length == length)) {
gsize i;
array = g_byte_array_sized_new (length);
buf_len = length;
buf_arr = g_new (guint8, buf_len);
for (i = 0; i < length; i++) {
int val = tmp_list[i];
const guint8 v = (guint8) (val & 0xFF);
@ -627,38 +638,42 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
_("ignoring invalid byte element '%d' (not between 0 and 255 inclusive)"),
val);
g_byte_array_free (array, TRUE);
g_free (tmp_list);
return;
}
g_byte_array_append (array, &v, 1);
buf_arr[i] = v;
}
}
g_free (tmp_list);
}
if (!array) {
if (!buf_arr) {
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
_("ignoring invalid MAC address"));
return;
}
mac_str = nm_utils_hwaddr_ntoa (array->data, array->len);
tmp_string = nm_utils_hwaddr_ntoa (buf_arr, buf_len);
mac_str = tmp_string;
out:
g_object_set (setting, key, mac_str, NULL);
g_free (mac_str);
g_byte_array_free (array, TRUE);
}
static void
mac_address_parser_ETHER (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
{
mac_address_parser (info, setting, key, ETH_ALEN);
mac_address_parser (info, setting, key, ETH_ALEN, FALSE);
}
static void
mac_address_parser_ETHER_cloned (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
{
mac_address_parser (info, setting, key, ETH_ALEN, TRUE);
}
static void
mac_address_parser_INFINIBAND (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
{
mac_address_parser (info, setting, key, INFINIBAND_ALEN);
mac_address_parser (info, setting, key, INFINIBAND_ALEN, FALSE);
}
static void
@ -1209,7 +1224,7 @@ static KeyParser key_parsers[] = {
{ NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
TRUE,
mac_address_parser_ETHER },
mac_address_parser_ETHER_cloned },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_MAC_ADDRESS,
TRUE,
@ -1217,7 +1232,7 @@ static KeyParser key_parsers[] = {
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
TRUE,
mac_address_parser_ETHER },
mac_address_parser_ETHER_cloned },
{ NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_BSSID,
TRUE,

View File

@ -63,6 +63,7 @@ typedef struct {
typedef struct {
char *id;
char *uuid;
char *stable_id;
char *interface_name;
char *type;
char *master;
@ -99,6 +100,7 @@ enum {
PROP_GATEWAY_PING_TIMEOUT,
PROP_METERED,
PROP_LLDP,
PROP_STABLE_ID,
LAST_PROP
};
@ -230,6 +232,24 @@ nm_setting_connection_get_uuid (NMSettingConnection *setting)
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->uuid;
}
/**
* nm_setting_connection_get_stable_id:
* @setting: the #NMSettingConnection
*
* Returns the #NMSettingConnection:stable_id property of the connection.
*
* Returns: the stable-id for the connection
*
* Since: 1.4
**/
const char *
nm_setting_connection_get_stable_id (NMSettingConnection *setting)
{
g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->stable_id;
}
/**
* nm_setting_connection_get_interface_name:
* @setting: the #NMSettingConnection
@ -1128,6 +1148,7 @@ finalize (GObject *object)
g_free (priv->id);
g_free (priv->uuid);
g_free (priv->stable_id);
g_free (priv->interface_name);
g_free (priv->type);
g_free (priv->zone);
@ -1174,6 +1195,10 @@ set_property (GObject *object, guint prop_id,
g_free (priv->uuid);
priv->uuid = g_value_dup_string (value);
break;
case PROP_STABLE_ID:
g_free (priv->stable_id);
priv->stable_id = g_value_dup_string (value);
break;
case PROP_INTERFACE_NAME:
g_free (priv->interface_name);
priv->interface_name = g_value_dup_string (value);
@ -1260,6 +1285,9 @@ get_property (GObject *object, guint prop_id,
case PROP_UUID:
g_value_set_string (value, nm_setting_connection_get_uuid (setting));
break;
case PROP_STABLE_ID:
g_value_set_string (value, nm_setting_connection_get_stable_id (setting));
break;
case PROP_INTERFACE_NAME:
g_value_set_string (value, nm_setting_connection_get_interface_name (setting));
break;
@ -1368,7 +1396,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
* property: uuid
* variable: UUID(+)
* description: UUID for the connection profile. When missing, NetworkManager
* creates the UUID itself (by hashing the file).
* creates the UUID itself (by hashing the filename).
* ---end---
*/
g_object_class_install_property
@ -1379,6 +1407,33 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingConnection:stable-id:
*
* This token to generate stable IDs for the connection. If unset,
* the UUID will be used instead.
*
* The stable-id is used instead of the connection UUID for generating
* IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy.
* It is also used to seed the generated cloned MAC address for
* ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable.
*
* Since: 1.4
**/
/* ---ifcfg-rh---
* property: stable-id
* variable: STABLE_ID(+)
* description: Token to generate stable IDs.
* ---end---
*/
g_object_class_install_property
(object_class, PROP_STABLE_ID,
g_param_spec_string (NM_SETTING_CONNECTION_STABLE_ID, "", "",
NULL,
G_PARAM_READWRITE |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingConnection:interface-name:
*

View File

@ -46,6 +46,7 @@ G_BEGIN_DECLS
#define NM_SETTING_CONNECTION_ID "id"
#define NM_SETTING_CONNECTION_UUID "uuid"
#define NM_SETTING_CONNECTION_STABLE_ID "stable-id"
#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name"
#define NM_SETTING_CONNECTION_TYPE "type"
#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect"
@ -116,6 +117,8 @@ GType nm_setting_connection_get_type (void);
NMSetting * nm_setting_connection_new (void);
const char *nm_setting_connection_get_id (NMSettingConnection *setting);
const char *nm_setting_connection_get_uuid (NMSettingConnection *setting);
NM_AVAILABLE_IN_1_4
const char *nm_setting_connection_get_stable_id (NMSettingConnection *setting);
const char *nm_setting_connection_get_interface_name (NMSettingConnection *setting);
const char *nm_setting_connection_get_connection_type (NMSettingConnection *setting);
gboolean nm_setting_connection_get_autoconnect (NMSettingConnection *setting);

View File

@ -299,6 +299,52 @@ nm_ip_address_unref (NMIPAddress *address)
}
}
/**
* _nm_ip_address_equal:
* @address: the #NMIPAddress
* @other: the #NMIPAddress to compare @address to.
* @consider_attributes: whether to check for equality of attributes too.
*
* Determines if two #NMIPAddress objects are equal.
*
* Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
**/
static gboolean
_nm_ip_address_equal (NMIPAddress *address, NMIPAddress *other, gboolean consider_attributes)
{
g_return_val_if_fail (address != NULL, FALSE);
g_return_val_if_fail (address->refcount > 0, FALSE);
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
if ( address->family != other->family
|| address->prefix != other->prefix
|| strcmp (address->address, other->address) != 0)
return FALSE;
if (consider_attributes) {
GHashTableIter iter;
const char *key;
GVariant *value, *value2;
guint n;
n = address->attributes ? g_hash_table_size (address->attributes) : 0;
if (n != (other->attributes ? g_hash_table_size (other->attributes) : 0))
return FALSE;
if (n) {
g_hash_table_iter_init (&iter, address->attributes);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
value2 = g_hash_table_lookup (other->attributes, key);
if (!value2)
return FALSE;
if (!g_variant_equal (value, value2))
return FALSE;
}
}
}
return TRUE;
}
/**
* nm_ip_address_equal:
* @address: the #NMIPAddress
@ -312,17 +358,7 @@ nm_ip_address_unref (NMIPAddress *address)
gboolean
nm_ip_address_equal (NMIPAddress *address, NMIPAddress *other)
{
g_return_val_if_fail (address != NULL, FALSE);
g_return_val_if_fail (address->refcount > 0, FALSE);
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (other->refcount > 0, FALSE);
if ( address->family != other->family
|| address->prefix != other->prefix
|| strcmp (address->address, other->address) != 0)
return FALSE;
return TRUE;
return _nm_ip_address_equal (address, other, FALSE);
}
/**
@ -717,17 +753,18 @@ nm_ip_route_unref (NMIPRoute *route)
}
/**
* nm_ip_route_equal:
* _nm_ip_route_equal:
* @route: the #NMIPRoute
* @other: the #NMIPRoute to compare @route to.
* @consider_attributes: whether to compare attributes too
*
* Determines if two #NMIPRoute objects contain the same destination, prefix,
* next hop, and metric. (Attributes are not compared.)
* next hop, and metric.
*
* Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
**/
gboolean
nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other)
static gboolean
_nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other, gboolean consider_attributes)
{
g_return_val_if_fail (route != NULL, FALSE);
g_return_val_if_fail (route->refcount > 0, FALSE);
@ -740,9 +777,45 @@ nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other)
|| strcmp (route->dest, other->dest) != 0
|| g_strcmp0 (route->next_hop, other->next_hop) != 0)
return FALSE;
if (consider_attributes) {
GHashTableIter iter;
const char *key;
GVariant *value, *value2;
guint n;
n = route->attributes ? g_hash_table_size (route->attributes) : 0;
if (n != (other->attributes ? g_hash_table_size (other->attributes) : 0))
return FALSE;
if (n) {
g_hash_table_iter_init (&iter, route->attributes);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
value2 = g_hash_table_lookup (other->attributes, key);
if (!value2)
return FALSE;
if (!g_variant_equal (value, value2))
return FALSE;
}
}
}
return TRUE;
}
/**
* nm_ip_route_equal:
* @route: the #NMIPRoute
* @other: the #NMIPRoute to compare @route to.
*
* Determines if two #NMIPRoute objects contain the same destination, prefix,
* next hop, and metric. (Attributes are not compared.)
*
* Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
**/
gboolean
nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other)
{
return _nm_ip_route_equal (route, other, FALSE);
}
/**
* nm_ip_route_dup:
* @route: the #NMIPRoute
@ -2306,6 +2379,48 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
static gboolean
compare_property (NMSetting *setting,
NMSetting *other,
const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingIPConfigPrivate *a_priv, *b_priv;
NMSettingClass *parent_class;
guint i;
if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ADDRESSES)) {
a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
if (a_priv->addresses->len != b_priv->addresses->len)
return FALSE;
for (i = 0; i < a_priv->addresses->len; i++) {
if (!_nm_ip_address_equal (a_priv->addresses->pdata[i], b_priv->addresses->pdata[i], TRUE))
return FALSE;
}
return TRUE;
}
if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ROUTES)) {
a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
if (a_priv->routes->len != b_priv->routes->len)
return FALSE;
for (i = 0; i < a_priv->routes->len; i++) {
if (!_nm_ip_route_equal (a_priv->routes->pdata[i], b_priv->routes->pdata[i], TRUE))
return FALSE;
}
return TRUE;
}
/* Otherwise chain up to parent to handle generic compare */
parent_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class);
return parent_class->compare_property (setting, other, prop_spec, flags);
}
/*****************************************************************************/
static void
nm_setting_ip_config_init (NMSettingIPConfig *setting)
@ -2536,6 +2651,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
parent_class->compare_property = compare_property;
/* Properties */

View File

@ -28,6 +28,7 @@
#include <net/ethernet.h>
#include "nm-utils.h"
#include "nm-common-macros.h"
#include "nm-utils-private.h"
#include "nm-setting-private.h"
@ -52,6 +53,7 @@ typedef struct {
gboolean auto_negotiate;
char *device_mac_address;
char *cloned_mac_address;
char *generate_mac_address_mask;
GArray *mac_address_blacklist;
guint32 mtu;
char **s390_subchannels;
@ -69,6 +71,7 @@ enum {
PROP_AUTO_NEGOTIATE,
PROP_MAC_ADDRESS,
PROP_CLONED_MAC_ADDRESS,
PROP_GENERATE_MAC_ADDRESS_MASK,
PROP_MAC_ADDRESS_BLACKLIST,
PROP_MTU,
PROP_S390_SUBCHANNELS,
@ -187,6 +190,22 @@ nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting)
return NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address;
}
/**
* nm_setting_wired_get_generate_mac_address_mask:
* @setting: the #NMSettingWired
*
* Returns: the #NMSettingWired:generate-mac-address-mask property of the setting
*
* Since: 1.4
**/
const char *
nm_setting_wired_get_generate_mac_address_mask (NMSettingWired *setting)
{
g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
return NM_SETTING_WIRED_GET_PRIVATE (setting)->generate_mac_address_mask;
}
/**
* nm_setting_wired_get_mac_address_blacklist:
* @setting: the #NMSettingWired
@ -611,6 +630,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
GHashTableIter iter;
const char *key, *value;
int i;
GError *local = NULL;
if (priv->port && !g_strv_contains (valid_ports, priv->port)) {
g_set_error (error,
@ -692,7 +712,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
}
if (priv->cloned_mac_address && !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
if ( priv->cloned_mac_address
&& !NM_CLONED_MAC_IS_SPECIAL (priv->cloned_mac_address)
&& !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
@ -701,6 +723,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
/* generate-mac-address-mask only makes sense with cloned-mac-address "random" or
* "stable". Still, let's not be so strict about that and accept the value
* even if it is unused. */
if (!_nm_utils_generate_mac_address_mask_parse (priv->generate_mac_address_mask,
NULL, NULL, NULL, &local)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
local->message);
g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK);
g_error_free (local);
return FALSE;
}
if ( NM_FLAGS_ANY (priv->wol, NM_SETTING_WIRED_WAKE_ON_LAN_EXCLUSIVE_FLAGS)
&& !nm_utils_is_power_of_two (priv->wol)) {
g_set_error_literal (error,
@ -732,6 +768,25 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
static gboolean
compare_property (NMSetting *setting,
NMSetting *other,
const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingClass *parent_class;
if (nm_streq (prop_spec->name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) {
return nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address,
NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address);
}
parent_class = NM_SETTING_CLASS (nm_setting_wired_parent_class);
return parent_class->compare_property (setting, other, prop_spec, flags);
}
/*****************************************************************************/
static void
clear_blacklist_item (char **item_p)
{
@ -763,6 +818,7 @@ finalize (GObject *object)
g_free (priv->device_mac_address);
g_free (priv->cloned_mac_address);
g_free (priv->generate_mac_address_mask);
g_array_unref (priv->mac_address_blacklist);
if (priv->s390_subchannels)
@ -807,6 +863,10 @@ set_property (GObject *object, guint prop_id,
priv->cloned_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
ETH_ALEN);
break;
case PROP_GENERATE_MAC_ADDRESS_MASK:
g_free (priv->generate_mac_address_mask);
priv->generate_mac_address_mask = g_value_dup_string (value);
break;
case PROP_MAC_ADDRESS_BLACKLIST:
blacklist = g_value_get_boxed (value);
g_array_set_size (priv->mac_address_blacklist, 0);
@ -872,6 +932,9 @@ get_property (GObject *object, guint prop_id,
case PROP_CLONED_MAC_ADDRESS:
g_value_set_string (value, nm_setting_wired_get_cloned_mac_address (setting));
break;
case PROP_GENERATE_MAC_ADDRESS_MASK:
g_value_set_string (value, nm_setting_wired_get_generate_mac_address_mask (setting));
break;
case PROP_MAC_ADDRESS_BLACKLIST:
g_value_set_boxed (value, (char **) priv->mac_address_blacklist->data);
break;
@ -900,18 +963,19 @@ get_property (GObject *object, guint prop_id,
}
static void
nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
GObjectClass *object_class = G_OBJECT_CLASS (setting_wired_class);
NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wired_class);
g_type_class_add_private (setting_class, sizeof (NMSettingWiredPrivate));
g_type_class_add_private (setting_wired_class, sizeof (NMSettingWiredPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
setting_class->verify = verify;
setting_class->compare_property = compare_property;
/* Properties */
/**
@ -1023,7 +1087,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
G_PARAM_READWRITE |
NM_SETTING_PARAM_INFERRABLE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_MAC_ADDRESS,
_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_to_dbus,
_nm_utils_hwaddr_from_dbus);
@ -1033,6 +1097,20 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
*
* If specified, request that the device use this MAC address instead of its
* permanent MAC address. This is known as MAC cloning or spoofing.
*
* Beside explicitly specifing a MAC address, the special values "preserve", "permanent",
* "random" and "stable" are supported.
* "preserve" means not to touch the MAC address on activation.
* "permanent" means to use the permanent hardware address of the device.
* "random" creates a random MAC address on each connect.
* "stable" creates a hashed MAC address based on connection.stable-id (or
* the connection's UUID) and a machine dependent key.
*
* If unspecified, the value can be overwritten via global defaults, see manual
* of NetworkManager.conf. If still unspecified, it defaults to "permanent".
*
* On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated
* "cloned-mac-address".
**/
/* ---keyfile---
* property: cloned-mac-address
@ -1047,6 +1125,12 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
* description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons
* notation (e.g. 00:22:68:14:5A:99).
* ---end---
* ---dbus---
* property: cloned-mac-address
* format: byte array
* description: This D-Bus field is deprecated in favor of "assigned-mac-address"
* which is more flexible and allows specifying special variants like "random".
* ---end---
*/
g_object_class_install_property
(object_class, PROP_CLONED_MAC_ADDRESS,
@ -1055,10 +1139,75 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
G_PARAM_READWRITE |
NM_SETTING_PARAM_INFERRABLE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_to_dbus,
_nm_utils_hwaddr_from_dbus);
_nm_setting_class_override_property (setting_class,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_cloned_get,
_nm_utils_hwaddr_cloned_set,
_nm_utils_hwaddr_cloned_not_set);
/* ---dbus---
* property: assigned-mac-address
* format: string
* description: The new field for the cloned MAC address. It can be either
* a hardware address in ASCII representation, or one of the special values
* "preserve", "permanent", "random", "random" or "stable".
* This field replaces the deprecated "cloned-mac-address" on D-Bus, which
* can only contain explict hardware addresses.
* ---end---
*/
_nm_setting_class_add_dbus_only_property (setting_class,
"assigned-mac-address",
G_VARIANT_TYPE_STRING,
_nm_utils_hwaddr_cloned_data_synth,
_nm_utils_hwaddr_cloned_data_set);
/**
* NMSettingWired:generate-mac-address-mask:
*
* With #NMSettingWired:cloned-mac-address setting "random" or "stable",
* by default all bits of the MAC address are scrambled and a locally-administered,
* unicast MAC address is created. This property allows to specify that certain bits
* are fixed. Note that the least significant bit of the first MAC address will
* always be unset to create a unicast MAC address.
*
* If the property is %NULL, it is eligible to be overwritten by a default
* connection setting. If the value is still %NULL or an empty string, the
* default is to create a locally-administered, unicast MAC address.
*
* If the value contains one MAC address, this address is used as mask. The set
* bits of the mask are to be filled with the current MAC address of the device,
* while the unset bits are subject to randomization.
* Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address
* and only randomize the lower 3 bytes using the "random" or "stable" algorithm.
*
* If the value contains one additional MAC address after the mask,
* this address is used instead of the current MAC address to fill the bits
* that shall not be randomized. For example, a value of
* "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address
* to 68:F7:28, while the lower bits are randomized. A value of
* "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled
* globally-administered, burned-in MAC address.
*
* If the value contains more then one additional MAC addresses, one of
* them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00"
* will create a fully scrambled MAC address, randomly locally or globally
* administered.
**/
/* ---ifcfg-rh---
* property: generate-mac-address-mask
* variable: GENERATE_MAC_ADDRESS_MASK
* description: the MAC address mask for generating randomized and stable
* cloned-mac-address.
* ---end---
*/
g_object_class_install_property
(object_class, PROP_GENERATE_MAC_ADDRESS_MASK,
g_param_spec_string (NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, "", "",
NULL,
G_PARAM_READWRITE |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingWired:mac-address-blacklist:
@ -1183,7 +1332,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
G_PARAM_READWRITE |
NM_SETTING_PARAM_INFERRABLE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_S390_OPTIONS,
_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_S390_OPTIONS,
G_VARIANT_TYPE ("a{ss}"),
_nm_utils_strdict_to_dbus,
_nm_utils_strdict_from_dbus);

View File

@ -85,6 +85,7 @@ typedef enum { /*< flags >*/
#define NM_SETTING_WIRED_AUTO_NEGOTIATE "auto-negotiate"
#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address"
#define NM_SETTING_WIRED_CLONED_MAC_ADDRESS "cloned-mac-address"
#define NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask"
#define NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST "mac-address-blacklist"
#define NM_SETTING_WIRED_MTU "mtu"
#define NM_SETTING_WIRED_S390_SUBCHANNELS "s390-subchannels"
@ -117,6 +118,9 @@ gboolean nm_setting_wired_get_auto_negotiate (NMSettingWired *setting
const char * nm_setting_wired_get_mac_address (NMSettingWired *setting);
const char * nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting);
NM_AVAILABLE_IN_1_4
const char * nm_setting_wired_get_generate_mac_address_mask (NMSettingWired *setting);
const char * const *nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting);
guint32 nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting);
const char * nm_setting_wired_get_mac_blacklist_item (NMSettingWired *setting,

View File

@ -22,11 +22,13 @@
#include "nm-default.h"
#include "nm-setting-wireless.h"
#include <string.h>
#include <net/ethernet.h>
#include "nm-setting-wireless.h"
#include "nm-utils.h"
#include "nm-common-macros.h"
#include "nm-utils-private.h"
#include "nm-setting-private.h"
@ -54,6 +56,7 @@ typedef struct {
guint32 tx_power;
char *device_mac_address;
char *cloned_mac_address;
char *generate_mac_address_mask;
GArray *mac_address_blacklist;
guint32 mtu;
GSList *seen_bssids;
@ -73,6 +76,7 @@ enum {
PROP_TX_POWER,
PROP_MAC_ADDRESS,
PROP_CLONED_MAC_ADDRESS,
PROP_GENERATE_MAC_ADDRESS_MASK,
PROP_MAC_ADDRESS_BLACKLIST,
PROP_MTU,
PROP_SEEN_BSSIDS,
@ -419,6 +423,22 @@ nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting)
return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address;
}
/**
* nm_setting_wireless_get_generate_mac_address_mask:
* @setting: the #NMSettingWireless
*
* Returns: the #NMSettingWireless:generate-mac-address-mask property of the setting
*
* Since: 1.4
**/
const char *
nm_setting_wireless_get_generate_mac_address_mask (NMSettingWireless *setting)
{
g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->generate_mac_address_mask;
}
/**
* nm_setting_wireless_get_mac_address_blacklist:
* @setting: the #NMSettingWireless
@ -721,6 +741,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
GSList *iter;
int i;
gsize length;
GError *local = NULL;
if (!priv->ssid) {
g_set_error_literal (error,
@ -801,7 +822,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
if (priv->cloned_mac_address && !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
if ( priv->cloned_mac_address
&& !NM_CLONED_MAC_IS_SPECIAL (priv->cloned_mac_address)
&& !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
@ -810,6 +833,20 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
/* generate-mac-address-mask only makes sense with cloned-mac-address "random" or
* "stable". Still, let's not be so strict about that and accept the value
* even if it is unused. */
if (!_nm_utils_generate_mac_address_mask_parse (priv->generate_mac_address_mask,
NULL, NULL, NULL, &local)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
local->message);
g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK);
g_error_free (local);
return FALSE;
}
for (i = 0; i < priv->mac_address_blacklist->len; i++) {
const char *mac = g_array_index (priv->mac_address_blacklist, const char *, i);
@ -836,9 +873,61 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
}
if (!NM_IN_SET (priv->mac_address_randomization,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
NM_SETTING_MAC_RANDOMIZATION_NEVER,
NM_SETTING_MAC_RANDOMIZATION_ALWAYS)) {
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid value"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION);
return FALSE;
}
/* from here on, check for NM_SETTING_VERIFY_NORMALIZABLE conditions. */
if (priv->cloned_mac_address) {
if ( priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_ALWAYS
&& nm_streq (priv->cloned_mac_address, "random"))
goto mac_addr_rand_ok;
if ( priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_NEVER
&& nm_streq (priv->cloned_mac_address, "permanent"))
goto mac_addr_rand_ok;
if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT)
goto mac_addr_rand_ok;
} else if (priv->mac_address_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT)
goto mac_addr_rand_ok;
g_set_error (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("conflicting value of mac-address-randomization and cloned-mac-address"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS);
return NM_SETTING_VERIFY_NORMALIZABLE;
mac_addr_rand_ok:
return TRUE;
}
static gboolean
compare_property (NMSetting *setting,
NMSetting *other,
const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingClass *parent_class;
if (nm_streq (prop_spec->name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) {
return nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address,
NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address);
}
parent_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class);
return parent_class->compare_property (setting, other, prop_spec, flags);
}
/*****************************************************************************/
static GVariant *
nm_setting_wireless_get_security (NMSetting *setting,
NMConnection *connection,
@ -879,6 +968,7 @@ finalize (GObject *object)
g_free (priv->bssid);
g_free (priv->device_mac_address);
g_free (priv->cloned_mac_address);
g_free (priv->generate_mac_address_mask);
g_array_unref (priv->mac_address_blacklist);
g_slist_free_full (priv->seen_bssids, g_free);
@ -931,6 +1021,10 @@ set_property (GObject *object, guint prop_id,
priv->cloned_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
ETH_ALEN);
break;
case PROP_GENERATE_MAC_ADDRESS_MASK:
g_free (priv->generate_mac_address_mask);
priv->generate_mac_address_mask = g_value_dup_string (value);
break;
case PROP_MAC_ADDRESS_BLACKLIST:
blacklist = g_value_get_boxed (value);
g_array_set_size (priv->mac_address_blacklist, 0);
@ -998,6 +1092,9 @@ get_property (GObject *object, guint prop_id,
case PROP_CLONED_MAC_ADDRESS:
g_value_set_string (value, nm_setting_wireless_get_cloned_mac_address (setting));
break;
case PROP_GENERATE_MAC_ADDRESS_MASK:
g_value_set_string (value, nm_setting_wireless_get_generate_mac_address_mask (setting));
break;
case PROP_MAC_ADDRESS_BLACKLIST:
g_value_set_boxed (value, (char **) priv->mac_address_blacklist->data);
break;
@ -1023,18 +1120,19 @@ get_property (GObject *object, guint prop_id,
}
static void
nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
GObjectClass *object_class = G_OBJECT_CLASS (setting_wireless_class);
NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wireless_class);
g_type_class_add_private (setting_class, sizeof (NMSettingWirelessPrivate));
g_type_class_add_private (setting_wireless_class, sizeof (NMSettingWirelessPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
setting_class->verify = verify;
setting_class->compare_property = compare_property;
/* Properties */
/**
@ -1154,7 +1252,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_BSSID,
_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_BSSID,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_to_dbus,
_nm_utils_hwaddr_from_dbus);
@ -1231,7 +1329,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_MAC_ADDRESS,
_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_to_dbus,
_nm_utils_hwaddr_from_dbus);
@ -1239,8 +1337,22 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
/**
* NMSettingWireless:cloned-mac-address:
*
* If specified, request that the Wi-Fi device use this MAC address instead
* of its permanent MAC address. This is known as MAC cloning or spoofing.
* If specified, request that the device use this MAC address instead of its
* permanent MAC address. This is known as MAC cloning or spoofing.
*
* Beside explicitly specifing a MAC address, the special values "preserve", "permanent",
* "random" and "stable" are supported.
* "preserve" means not to touch the MAC address on activation.
* "permanent" means to use the permanent hardware address of the device.
* "random" creates a random MAC address on each connect.
* "stable" creates a hashed MAC address based on connection.stable-id (or
* the connection's UUID) and a machine dependent key.
*
* If unspecified, the value can be overwritten via global defaults, see manual
* of NetworkManager.conf. If still unspecified, it defaults to "permanent".
*
* On D-Bus, this field is expressed as "assigned-mac-address" or the deprecated
* "cloned-mac-address".
**/
/* ---keyfile---
* property: cloned-mac-address
@ -1255,6 +1367,12 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
* description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons
* notation (e.g. 00:22:68:14:5A:99).
* ---end---
* ---dbus---
* property: cloned-mac-address
* format: byte array
* description: This D-Bus field is deprecated in favor of "assigned-mac-address"
* which is more flexible and allows specifying special variants like "random".
* ---end---
*/
g_object_class_install_property
(object_class, PROP_CLONED_MAC_ADDRESS,
@ -1262,10 +1380,75 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_to_dbus,
_nm_utils_hwaddr_from_dbus);
_nm_setting_class_override_property (setting_class,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
G_VARIANT_TYPE_BYTESTRING,
_nm_utils_hwaddr_cloned_get,
_nm_utils_hwaddr_cloned_set,
_nm_utils_hwaddr_cloned_not_set);
/* ---dbus---
* property: assigned-mac-address
* format: string
* description: The new field for the cloned MAC address. It can be either
* a hardware address in ASCII representation, or one of the special values
* "preserve", "permanent", "random", "random" or "stable".
* This field replaces the deprecated "cloned-mac-address" on D-Bus, which
* can only contain explict hardware addresses.
* ---end---
*/
_nm_setting_class_add_dbus_only_property (setting_class,
"assigned-mac-address",
G_VARIANT_TYPE_STRING,
_nm_utils_hwaddr_cloned_data_synth,
_nm_utils_hwaddr_cloned_data_set);
/**
* NMSettingWireless:generate-mac-address-mask:
*
* With #NMSettingWireless:cloned-mac-address setting "random" or "stable",
* by default all bits of the MAC address are scrambled and a locally-administered,
* unicast MAC address is created. This property allows to specify that certain bits
* are fixed. Note that the least significant bit of the first MAC address will
* always be unset to create a unicast MAC address.
*
* If the property is %NULL, it is eligible to be overwritten by a default
* connection setting. If the value is still %NULL or an empty string, the
* default is to create a locally-administered, unicast MAC address.
*
* If the value contains one MAC address, this address is used as mask. The set
* bits of the mask are to be filled with the current MAC address of the device,
* while the unset bits are subject to randomization.
* Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the current MAC address
* and only randomize the lower 3 bytes using the "random" or "stable" algorithm.
*
* If the value contains one additional MAC address after the mask,
* this address is used instead of the current MAC address to fill the bits
* that shall not be randomized. For example, a value of
* "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC address
* to 68:F7:28, while the lower bits are randomized. A value of
* "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled
* globally-administered, burned-in MAC address.
*
* If the value contains more then one additional MAC addresses, one of
* them is chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00"
* will create a fully scrambled MAC address, randomly locally or globally
* administered.
**/
/* ---ifcfg-rh---
* property: generate-mac-address-mask
* variable: GENERATE_MAC_ADDRESS_MASK
* description: the MAC address mask for generating randomized and stable
* cloned-mac-address.
* ---end---
*/
g_object_class_install_property
(object_class, PROP_GENERATE_MAC_ADDRESS_MASK,
g_param_spec_string (NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, "", "",
NULL,
G_PARAM_READWRITE |
NM_SETTING_PARAM_FUZZY_IGNORE |
G_PARAM_STATIC_STRINGS));
/**
* NMSettingWireless:mac-address-blacklist:
@ -1398,6 +1581,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
* (always randomize the MAC address).
*
* Since: 1.2
* Deprecated: 1.4: Deprecated by NMSettingWireless:cloned-mac-address property
**/
/* ---ifcfg-rh---
* property: mac-address-randomization
@ -1428,7 +1612,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
* NetworkManager daemons.
* ---end---
*/
_nm_setting_class_add_dbus_only_property (parent_class, "security",
_nm_setting_class_add_dbus_only_property (setting_class, "security",
G_VARIANT_TYPE_STRING,
nm_setting_wireless_get_security, NULL);
}

View File

@ -50,6 +50,7 @@ G_BEGIN_DECLS
#define NM_SETTING_WIRELESS_TX_POWER "tx-power"
#define NM_SETTING_WIRELESS_MAC_ADDRESS "mac-address"
#define NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS "cloned-mac-address"
#define NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK "generate-mac-address-mask"
#define NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST "mac-address-blacklist"
#define NM_SETTING_WIRELESS_MTU "mtu"
#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
@ -126,6 +127,9 @@ guint32 nm_setting_wireless_get_tx_power (NMSettingWireless
const char *nm_setting_wireless_get_mac_address (NMSettingWireless *setting);
const char *nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting);
NM_AVAILABLE_IN_1_4
const char *nm_setting_wireless_get_generate_mac_address_mask (NMSettingWireless *setting);
const char * const *nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting);
guint32 nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting);
const char * nm_setting_wireless_get_mac_blacklist_item (NMSettingWireless *setting,

View File

@ -36,6 +36,29 @@ gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, g
/* D-Bus transform funcs */
GVariant *_nm_utils_hwaddr_cloned_get (NMSetting *setting,
const char *property);
gboolean _nm_utils_hwaddr_cloned_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
GVariant *value,
NMSettingParseFlags parse_flags,
GError **error);
gboolean _nm_utils_hwaddr_cloned_not_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
NMSettingParseFlags parse_flags,
GError **error);
GVariant * _nm_utils_hwaddr_cloned_data_synth (NMSetting *setting,
NMConnection *connection,
const char *property);
gboolean _nm_utils_hwaddr_cloned_data_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
GVariant *value,
NMSettingParseFlags parse_flags,
GError **error);
GVariant * _nm_utils_hwaddr_to_dbus (const GValue *prop_value);
void _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
GValue *prop_value);

View File

@ -37,6 +37,7 @@
#include <jansson.h>
#endif
#include "nm-common-macros.h"
#include "nm-utils-private.h"
#include "nm-setting-private.h"
#include "crypto.h"
@ -3114,6 +3115,33 @@ hwaddr_binary_len (const char *asc)
return octets;
}
/**
* _nm_utils_hwaddr_length:
* @asc: the ASCII representation of the hardware address
*
* Validates that @asc is a valid representation of a hardware
* address up to (including) %NM_UTILS_HWADDR_LEN_MAX bytes.
*
* Returns: binary length of the hardware address @asc or
* 0 on error.
*/
guint
_nm_utils_hwaddr_length (const char *asc)
{
int l;
if (!asc)
return 0;
l = hwaddr_binary_len (asc);
if (l <= 0 || l > NM_UTILS_HWADDR_LEN_MAX)
return 0;
if (!nm_utils_hwaddr_valid (asc, l))
return 0;
return l;
}
/**
* nm_utils_hwaddr_valid:
* @asc: the ASCII representation of a hardware address
@ -3286,24 +3314,124 @@ nm_utils_hwaddr_matches (gconstpointer hwaddr1,
return !memcmp (hwaddr1, hwaddr2, hwaddr1_len);
}
GVariant *
_nm_utils_hwaddr_to_dbus (const GValue *prop_value)
/*****************************************************************************/
static GVariant *
_nm_utils_hwaddr_to_dbus_impl (const char *str)
{
const char *str = g_value_get_string (prop_value);
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
int len;
if (str) {
len = hwaddr_binary_len (str);
g_return_val_if_fail (len > 0 && len <= NM_UTILS_HWADDR_LEN_MAX, NULL);
if (!nm_utils_hwaddr_aton (str, buf, len))
len = 0;
} else
len = 0;
if (!str)
return NULL;
len = _nm_utils_hwaddr_length (str);
if (len == 0)
return NULL;
if (!nm_utils_hwaddr_aton (str, buf, len))
return NULL;
return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, buf, len, 1);
}
GVariant *
_nm_utils_hwaddr_cloned_get (NMSetting *setting,
const char *property)
{
gs_free char *addr = NULL;
nm_assert (nm_streq0 (property, "cloned-mac-address"));
g_object_get (setting, "cloned-mac-address", &addr, NULL);
return _nm_utils_hwaddr_to_dbus_impl (addr);
}
gboolean
_nm_utils_hwaddr_cloned_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
GVariant *value,
NMSettingParseFlags parse_flags,
GError **error)
{
gsize length;
const guint8 *array;
char *str;
nm_assert (nm_streq0 (property, "cloned-mac-address"));
if (!_nm_setting_use_legacy_property (setting, connection_dict, "cloned-mac-address", "assigned-mac-address"))
return TRUE;
length = 0;
array = g_variant_get_fixed_array (value, &length, 1);
if (!length)
return TRUE;
str = nm_utils_hwaddr_ntoa (array, length);
g_object_set (setting,
"cloned-mac-address",
str,
NULL);
g_free (str);
return TRUE;
}
gboolean
_nm_utils_hwaddr_cloned_not_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
NMSettingParseFlags parse_flags,
GError **error)
{
nm_assert (nm_streq0 (property, "cloned-mac-address"));
return TRUE;
}
GVariant *
_nm_utils_hwaddr_cloned_data_synth (NMSetting *setting,
NMConnection *connection,
const char *property)
{
gs_free char *addr = NULL;
nm_assert (nm_streq0 (property, "assigned-mac-address"));
g_object_get (setting,
"cloned-mac-address",
&addr,
NULL);
return addr ? g_variant_new_string (addr) : NULL;
}
gboolean
_nm_utils_hwaddr_cloned_data_set (NMSetting *setting,
GVariant *connection_dict,
const char *property,
GVariant *value,
NMSettingParseFlags parse_flags,
GError **error)
{
nm_assert (nm_streq0 (property, "assigned-mac-address"));
if (_nm_setting_use_legacy_property (setting, connection_dict, "cloned-mac-address", "assigned-mac-address"))
return TRUE;
g_object_set (setting,
"cloned-mac-address",
g_variant_get_string (value, NULL),
NULL);
return TRUE;
}
GVariant *
_nm_utils_hwaddr_to_dbus (const GValue *prop_value)
{
return _nm_utils_hwaddr_to_dbus_impl (g_value_get_string (prop_value));
}
void
_nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
GValue *prop_value)
@ -3316,6 +3444,93 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
g_value_take_string (prop_value, str);
}
/*****************************************************************************/
static char *
_split_word (char *s)
{
/* takes @s and truncates the string on the first white-space.
* then it returns the first word afterwards (again seeking
* over leading white-space). */
for (; s[0]; s++) {
if (g_ascii_isspace (s[0])) {
s[0] = '\0';
s++;
while (g_ascii_isspace (s[0]))
s++;
return s;
}
}
return s;
}
gboolean
_nm_utils_generate_mac_address_mask_parse (const char *value,
struct ether_addr *out_mask,
struct ether_addr **out_ouis,
gsize *out_ouis_len,
GError **error)
{
gs_free char *s_free = NULL;
char *s, *s_next;
struct ether_addr mask;
gs_unref_array GArray *ouis = NULL;
g_return_val_if_fail (!error || !*error, FALSE);
if (!value || !*value) {
/* NULL and "" are valid values and both mean the default
* "q */
if (out_mask) {
memset (out_mask, 0, sizeof (*out_mask));
out_mask->ether_addr_octet[0] |= 0x02;
}
NM_SET_OUT (out_ouis, NULL);
NM_SET_OUT (out_ouis_len, 0);
return TRUE;
}
s_free = g_strdup (value);
s = s_free;
/* skip over leading whitespace */
while (g_ascii_isspace (s[0]))
s++;
/* parse the first mask */
s_next = _split_word (s);
if (!nm_utils_hwaddr_aton (s, &mask, ETH_ALEN)) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
_("not a valid ethernet MAC address for mask at position %lld"),
(long long) (s - s_free));
return FALSE;
}
if (s_next[0]) {
ouis = g_array_sized_new (FALSE, FALSE, sizeof (struct ether_addr), 4);
do {
s = s_next;
s_next = _split_word (s);
g_array_set_size (ouis, ouis->len + 1);
if (!nm_utils_hwaddr_aton (s, &g_array_index (ouis, struct ether_addr, ouis->len - 1), ETH_ALEN)) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
_("not a valid ethernet MAC address #%u at position %lld"),
ouis->len, (long long) (s - s_free));
return FALSE;
}
} while (s_next[0]);
}
NM_SET_OUT (out_mask, mask);
NM_SET_OUT (out_ouis_len, ouis ? ouis->len : 0);
NM_SET_OUT (out_ouis, ouis ? ((struct ether_addr *) g_array_free (g_steal_pointer (&ouis), FALSE)) : NULL);
return TRUE;
}
/*****************************************************************************/
/**
* nm_utils_bin2hexstr:
* @src: (type guint8) (array length=len): an array of bytes

View File

@ -1916,6 +1916,7 @@ test_connection_diff_a_only (void)
{ NM_SETTING_CONNECTION_SETTING_NAME, {
{ NM_SETTING_CONNECTION_ID, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_CONNECTION_UUID, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A },
@ -1940,6 +1941,7 @@ test_connection_diff_a_only (void)
{ NM_SETTING_WIRED_AUTO_NEGOTIATE, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_CLONED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_MTU, NM_SETTING_DIFF_RESULT_IN_A },
{ NM_SETTING_WIRED_S390_SUBCHANNELS, NM_SETTING_DIFF_RESULT_IN_A },
@ -2384,6 +2386,154 @@ test_setting_compare_id (void)
g_assert (success);
}
static void
test_setting_compare_addresses (void)
{
gs_unref_object NMSetting *s1 = NULL, *s2 = NULL;
gboolean success;
NMIPAddress *a;
GHashTable *result = NULL;
s1 = nm_setting_ip4_config_new ();
s2 = nm_setting_ip4_config_new ();
a = nm_ip_address_new (AF_INET, "192.168.7.5", 24, NULL);
nm_ip_address_set_attribute (a, "label", g_variant_new_string ("xoxoxo"));
nm_setting_ip_config_add_address ((NMSettingIPConfig *) s1, a);
nm_ip_address_set_attribute (a, "label", g_variant_new_string ("hello"));
nm_setting_ip_config_add_address ((NMSettingIPConfig *) s2, a);
nm_ip_address_unref (a);
if (nmtst_get_rand_int () % 2)
NMTST_SWAP (s1, s2);
success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result);
g_assert (!success);
g_clear_pointer (&result, g_hash_table_unref);
}
static void
test_setting_compare_routes (void)
{
gs_unref_object NMSetting *s1 = NULL, *s2 = NULL;
gboolean success;
NMIPRoute *r;
GHashTable *result = NULL;
s1 = nm_setting_ip4_config_new ();
s2 = nm_setting_ip4_config_new ();
r = nm_ip_route_new (AF_INET, "192.168.12.0", 24, "192.168.11.1", 473, NULL);
nm_ip_route_set_attribute (r, "label", g_variant_new_string ("xoxoxo"));
nm_setting_ip_config_add_route ((NMSettingIPConfig *) s1, r);
nm_ip_route_set_attribute (r, "label", g_variant_new_string ("hello"));
nm_setting_ip_config_add_route ((NMSettingIPConfig *) s2, r);
nm_ip_route_unref (r);
if (nmtst_get_rand_int () % 2)
NMTST_SWAP (s1, s2);
success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result);
g_assert (!success);
g_clear_pointer (&result, g_hash_table_unref);
}
static void
test_setting_compare_wired_cloned_mac_address (void)
{
gs_unref_object NMSetting *old = NULL, *new = NULL;
gboolean success;
gs_free char *str1 = NULL;
old = nm_setting_wired_new ();
g_object_set (old,
NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable",
NULL);
g_assert_cmpstr ("stable", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) old));
g_object_get (old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("stable", ==, str1);
g_clear_pointer (&str1, g_free);
new = nm_setting_duplicate (old);
g_object_set (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL);
g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new));
g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("11:22:33:44:55:66", ==, str1);
g_clear_pointer (&str1, g_free);
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
g_clear_object (&new);
new = nm_setting_duplicate (old);
g_object_set (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable-bia", NULL);
g_assert_cmpstr ("stable-bia", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new));
g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("stable-bia", ==, str1);
g_clear_pointer (&str1, g_free);
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
g_clear_object (&new);
}
static void
test_setting_compare_wireless_cloned_mac_address (void)
{
gs_unref_object NMSetting *old = NULL, *new = NULL;
gboolean success;
gs_free char *str1 = NULL;
old = nm_setting_wireless_new ();
g_object_set (old,
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable",
NULL);
g_assert_cmpstr ("stable", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) old));
g_object_get (old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("stable", ==, str1);
g_clear_pointer (&str1, g_free);
new = nm_setting_duplicate (old);
g_object_set (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL);
g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new));
g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("11:22:33:44:55:66", ==, str1);
g_clear_pointer (&str1, g_free);
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
g_clear_object (&new);
new = nm_setting_duplicate (old);
g_object_set (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable-bia", NULL);
g_assert_cmpstr ("stable-bia", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new));
g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
g_assert_cmpstr ("stable-bia", ==, str1);
g_clear_pointer (&str1, g_free);
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
g_assert (!success);
g_clear_object (&new);
}
static void
test_setting_compare_timestamp (void)
{
@ -5135,6 +5285,10 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform);
g_test_add_func ("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum);
g_test_add_func ("/core/general/test_setting_compare_id", test_setting_compare_id);
g_test_add_func ("/core/general/test_setting_compare_addresses", test_setting_compare_addresses);
g_test_add_func ("/core/general/test_setting_compare_routes", test_setting_compare_routes);
g_test_add_func ("/core/general/test_setting_compare_wired_cloned_mac_address", test_setting_compare_wired_cloned_mac_address);
g_test_add_func ("/core/general/test_setting_compare_wirless_cloned_mac_address", test_setting_compare_wireless_cloned_mac_address);
g_test_add_func ("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp);
#define ADD_FUNC(name, func, secret_flags, comp_flags, remove_secret) \
g_test_add_data_func_full ("/core/general/" G_STRINGIFY (func) "_" name, \

View File

@ -1066,8 +1066,11 @@ libnm_1_2_4 {
libnm_1_4_0 {
global:
nm_device_team_get_config;
nm_setting_connection_get_stable_id;
nm_setting_ip6_config_get_token;
nm_setting_ip_config_get_dns_priority;
nm_setting_wired_get_generate_mac_address_mask;
nm_setting_wireless_get_generate_mac_address_mask;
nm_vpn_editor_plugin_get_plugin_info;
nm_vpn_editor_plugin_get_vt;
nm_vpn_editor_plugin_load;

View File

@ -224,30 +224,12 @@ no-auto-default=*
<term><varname>ignore-carrier</varname></term>
<listitem>
<para>
Specify devices for which NetworkManager will (partially)
ignore the carrier state. Normally, for
device types that support carrier-detect, such as Ethernet
and InfiniBand, NetworkManager will only allow a
connection to be activated on the device if carrier is
present (ie, a cable is plugged in), and it will
deactivate the device if carrier drops for more than a few
seconds.
</para>
<para>
Listing a device here will allow activating connections on
that device even when it does not have carrier, provided
that the connection uses only statically-configured IP
addresses. Additionally, it will allow any active
connection (whether static or dynamic) to remain active on
the device when carrier is lost.
</para>
<para>
Note that the "carrier" property of NMDevices and device D-Bus
interfaces will still reflect the actual device state; it's just
that NetworkManager will not make use of that information.
</para>
<para>See <xref linkend="device-spec"/> for the syntax how to
specify a device.
This setting is deprecated for the per-device setting
<literal>ignore-carrier</literal> which overwrites this setting
if specified (See <xref linked="ignore-carrier"/>).
Otherwise, it is a list of matches to specify for which device
carrier should be ignored. See <xref linkend="device-spec"/> for the
syntax how to specify a device.
</para>
</listitem>
</varlistentry>
@ -583,6 +565,13 @@ ipv6.ip6-privacy=0
<varlistentry>
<term><varname>connection.lldp</varname></term>
</varlistentry>
<varlistentry>
<term><varname>ethernet.cloned-mac-address</varname></term>
<listitem><para>If left unspecified, it defaults to "permanent".</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ethernet.generate-mac-address-mask</varname></term>
</varlistentry>
<varlistentry>
<term><varname>ethernet.wake-on-lan</varname></term>
</varlistentry>
@ -610,9 +599,18 @@ ipv6.ip6-privacy=0
<term><varname>vpn.timeout</varname></term>
<listitem><para>If left unspecified, default value of 60 seconds is used.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>wifi.cloned-mac-address</varname></term>
<listitem><para>If left unspecified, it defaults to "permanent".</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>wifi.generate-mac-address-mask</varname></term>
</varlistentry>
<varlistentry>
<term><varname>wifi.mac-address-randomization</varname></term>
<listitem><para>If left unspecified, MAC address randomization is disabled.</para></listitem>
<listitem><para>If left unspecified, MAC address randomization is disabled.
This setting is deprecated for <literal>wifi.cloned-mac-address</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>wifi.powersave</varname></term>
@ -623,7 +621,7 @@ ipv6.ip6-privacy=0
</para>
</refsect2>
<refsect2>
<refsect2 id="connection-sections">
<title>Sections</title>
<para>
You can configure multiple <literal>connection</literal>
@ -696,6 +694,97 @@ ipv6.ip6-privacy=1
</refsect2>
</refsect1>
<refsect1>
<title><literal>device</literal> section</title>
<para>Contains per-device persistent configuration.
</para>
<para>
Example:
<programlisting>
[device]
match-device=interface-name:eth3
unmanaged=1
</programlisting>
</para>
<refsect2>
<title>Supported Properties</title>
<para>
The following properties can be configured per-device.
<variablelist>
<varlistentry id="ignore-carrier">
<term><varname>ignore-carrier</varname></term>
<listitem>
<para>
Specify devices for which NetworkManager will (partially)
ignore the carrier state. Normally, for
device types that support carrier-detect, such as Ethernet
and InfiniBand, NetworkManager will only allow a
connection to be activated on the device if carrier is
present (ie, a cable is plugged in), and it will
deactivate the device if carrier drops for more than a few
seconds.
</para>
<para>
A device with carrier ignored will allow activating connections on
that device even when it does not have carrier, provided
that the connection uses only statically-configured IP
addresses. Additionally, it will allow any active
connection (whether static or dynamic) to remain active on
the device when carrier is lost.
</para>
<para>
Note that the "carrier" property of NMDevices and device D-Bus
interfaces will still reflect the actual device state; it's just
that NetworkManager will not make use of that information.
</para>
<para>
This setting overwrites the deprecated <literal>main.ignore-carrier</literal>
setting above.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>wifi.scan-rand-mac-address</varname></term>
<listitem>
<para>
Configures the MAC address of a Wi-Fi device during scanning.
This defaults to <literal>yes</literal> in which case a random,
locally-administered MAC address will be confiugred.
Otherwise, the MAC address is left unchanged to whatever was
configured.
For the MAC address used while the device is connected, see instead
the per-connection setting <literal>wifi.cloned-mac-address</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>wifi.scan-generate-mac-address-mask</varname></term>
<listitem>
<para>
Like the per-connection settings ethernet.generate-mac-address-mask
and wifi.generate-mac-address-mask, this allows to configure the
generated MAC addresses during scanning. See manual of nm-settings
for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
<refsect2>
<title>Sections</title>
<para>
The <literal>[device]</literal> section works the same as the <literal>[connection]</literal> section.
That is, multiple sections that all start with the prefix "device" can be specified.
The settings "match-device" and "stop-match" are available to match a device section
on a device. The order of multiple sections is also top-down within the file and
later files overwrite previous settings. See <xref linkend="connection-sections"/>
for details.
</para>
</refsect2>
</refsect1>
<refsect1>
<title><literal>connectivity</literal> section</title>
<para>This section controls NetworkManager's optional connectivity
@ -978,7 +1067,8 @@ enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16
<title>Device List Format</title>
<para>
The configuration options <literal>main.no-auto-default</literal>, <literal>main.ignore-carrier</literal>,
and <literal>keyfile.unmanaged-devices</literal> select devices based on a list of matchings.
<literal>keyfile.unmanaged-devices</literal>, <literal>connection*.match-device</literal> and
<literal>device*.match-device</literal> select devices based on a list of matchings.
Devices can be specified using the following format:
</para>
<para>
@ -993,7 +1083,7 @@ enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16
</varlistentry>
<varlistentry>
<term>HWADDR</term>
<listitem><para>Match the MAC address of the device. Globbing is not supported</para></listitem>
<listitem><para>Match the permanent MAC address of the device. Globbing is not supported</para></listitem>
</varlistentry>
<varlistentry>
<term>interface-name:IFNAME</term>
@ -1008,7 +1098,7 @@ enable=nm-version-min:1.3,nm-version-min:1.2.6,nm-version-min:1.0.16
</varlistentry>
<varlistentry>
<term>mac:HWADDR</term>
<listitem><para>Match the MAC address of the device. Globbing is not supported</para></listitem>
<listitem><para>Match the permanent MAC address of the device. Globbing is not supported</para></listitem>
</varlistentry>
<varlistentry>
<term>s390-subchannels:HWADDR</term>

View File

@ -257,6 +257,11 @@ DEVICETYPE=TeamPort
assigns the interface 10.42.0.1, or it uses the first static address,
if configured.</para>
</listitem>
<listitem>
<para><literal>HWADDR</literal> -
initscripts compare the currently set hardware address of a device, while
NetworkManager considers the permanent one.</para>
</listitem>
</itemizedlist>
</para></listitem>
</varlistentry>

View File

@ -38,6 +38,21 @@
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
#define NM_CLONED_MAC_PRESERVE "preserve"
#define NM_CLONED_MAC_PERMANENT "permanent"
#define NM_CLONED_MAC_RANDOM "random"
#define NM_CLONED_MAC_STABLE "stable"
static inline gboolean
NM_CLONED_MAC_IS_SPECIAL (const char *str)
{
return NM_IN_STRSET (str,
NM_CLONED_MAC_PRESERVE,
NM_CLONED_MAC_PERMANENT,
NM_CLONED_MAC_RANDOM,
NM_CLONED_MAC_STABLE);
}
/******************************************************************************/
#endif /* __NM_COMMON_MACROS_H__ */

View File

@ -529,8 +529,8 @@ check_connection_mac_address (NMConnection *orig,
static gboolean
check_connection_cloned_mac_address (NMConnection *orig,
NMConnection *candidate,
GHashTable *settings)
NMConnection *candidate,
GHashTable *settings)
{
GHashTable *props;
const char *orig_mac = NULL, *cand_mac = NULL;
@ -551,6 +551,12 @@ check_connection_cloned_mac_address (NMConnection *orig,
if (s_wired_cand)
cand_mac = nm_setting_wired_get_cloned_mac_address (s_wired_cand);
/* special cloned mac address entires are accepted. */
if (NM_CLONED_MAC_IS_SPECIAL (orig_mac))
orig_mac = NULL;
if (NM_CLONED_MAC_IS_SPECIAL (cand_mac))
cand_mac = NULL;
if (!orig_mac || !cand_mac) {
remove_from_hash (settings, props,
NM_SETTING_WIRED_SETTING_NAME,

View File

@ -1002,7 +1002,7 @@ nm_device_bt_new (NMBluezDevice *bt_device,
NM_DEVICE_UDI, udi,
NM_DEVICE_IFACE, bdaddr,
NM_DEVICE_DRIVER, "bluez",
NM_DEVICE_HW_ADDRESS, bdaddr,
NM_DEVICE_PERM_HW_ADDRESS, bdaddr,
NM_DEVICE_BT_DEVICE, bt_device,
NM_DEVICE_BT_NAME, name,
NM_DEVICE_BT_CAPABILITIES, capabilities,

View File

@ -120,7 +120,6 @@ typedef struct {
enum {
PROP_0,
PROP_PERM_HW_ADDRESS,
PROP_SPEED,
PROP_S390_SUBCHANNELS,
@ -307,14 +306,6 @@ nm_device_ethernet_init (NMDeviceEthernet *self)
priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
static void
realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->realize_start_notify (device, plink);
g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
}
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
@ -408,7 +399,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!match_subchans (self, s_wired, &try_mac))
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
mac = nm_setting_wired_get_mac_address (s_wired);
if (perm_hw_addr) {
if (try_mac && mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
@ -813,21 +804,17 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (dev);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMSettingWired *s_wired;
const char *cloned_mac;
NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
ret = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->act_stage1_prepare (dev, reason);
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
if (s_wired) {
/* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_ETHER);
}
if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE))
ret = NM_ACT_STAGE_RETURN_FAILURE;
}
if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
/* If we're re-activating a PPPoE connection a short while after
* a previous PPPoE connection was torn down, wait a bit to allow the
* remote side to handle the disconnection. Otherwise the peer may
@ -1365,10 +1352,6 @@ deactivate (NMDevice *device)
/* Set last PPPoE connection time */
if (nm_device_get_applied_setting (device, NM_TYPE_SETTING_PPPOE))
NM_DEVICE_ETHERNET_GET_PRIVATE (device)->last_pppoe_time = nm_utils_get_monotonic_timestamp_s ();
/* Reset MAC address back to initial address */
if (nm_device_get_initial_hw_address (device))
nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_ETHER);
}
static gboolean
@ -1409,7 +1392,7 @@ complete_connection (NMDevice *device,
nm_connection_add_setting (connection, NM_SETTING (s_wired));
}
perm_hw_addr = nm_device_get_permanent_hw_address (device);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
if (perm_hw_addr) {
setting_mac = nm_setting_wired_get_mac_address (s_wired);
if (setting_mac) {
@ -1438,7 +1421,7 @@ new_default_connection (NMDevice *self)
NMConnection *connection;
NMSettingsConnection *const*connections;
NMSetting *setting;
const char *hw_address;
const char *perm_hw_addr;
gs_free char *defname = NULL;
gs_free char *uuid = NULL;
gs_free char *machine_id = NULL;
@ -1446,8 +1429,8 @@ new_default_connection (NMDevice *self)
if (nm_config_get_no_auto_default_for_device (nm_config_get (), self))
return NULL;
hw_address = nm_device_get_hw_address (self);
if (!hw_address)
perm_hw_addr = nm_device_get_permanent_hw_address (self, FALSE);
if (!perm_hw_addr)
return NULL;
connection = nm_simple_connection_new ();
@ -1466,7 +1449,7 @@ new_default_connection (NMDevice *self)
uuid = _nm_utils_uuid_generate_from_strings ("default-wired",
machine_id ?: "",
defname,
hw_address,
perm_hw_addr,
NULL);
g_object_set (setting,
@ -1480,7 +1463,7 @@ new_default_connection (NMDevice *self)
/* Lock the connection to the device */
setting = nm_setting_wired_new ();
g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, hw_address, NULL);
g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, perm_hw_addr, NULL);
nm_connection_add_setting (connection, setting);
return connection;
@ -1506,7 +1489,7 @@ update_connection (NMDevice *device, NMConnection *connection)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
NMSettingWired *s_wired = nm_connection_get_setting_wired (connection);
const char *perm_hw_addr = nm_device_get_permanent_hw_address (device);
const char *perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
const char *mac = nm_device_get_hw_address (device);
const char *mac_prop = NM_SETTING_WIRED_MAC_ADDRESS;
GHashTableIter iter;
@ -1582,34 +1565,10 @@ link_changed (NMDevice *device, NMPlatformLink *info)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
const guint8 *hwaddr;
gsize hwaddrlen = 0;
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->link_changed (device, info);
if (!priv->subchan1 && info->initialized)
_update_s390_subchannels (self);
if (!nm_device_get_initial_hw_address (device)) {
hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET,
nm_device_get_ifindex (self),
&hwaddrlen);
if (!nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth))) {
_LOGD (LOGD_DEVICE, "device got a valid hw address");
nm_device_update_hw_address (self);
nm_device_update_initial_hw_address (self);
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) {
/*
* If the device is UNAVAILABLE, any previous try to
* bring it up probably has failed because of the
* invalid hardware address; try again.
*/
nm_device_bring_up (self, TRUE, NULL);
nm_device_queue_recheck_available (device,
NM_DEVICE_STATE_REASON_NONE,
NM_DEVICE_STATE_REASON_NONE);
}
}
}
}
static gboolean
@ -1663,9 +1622,6 @@ get_property (GObject *object, guint prop_id,
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
switch (prop_id) {
case PROP_PERM_HW_ADDRESS:
g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (object)));
break;
case PROP_SPEED:
g_value_set_uint (value, priv->speed);
break;
@ -1707,7 +1663,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
object_class->set_property = set_property;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->realize_start_notify = realize_start_notify;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
parent_class->new_default_connection = new_default_connection;
@ -1726,13 +1681,6 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->state_changed = device_state_changed;
/* properties */
g_object_class_install_property
(object_class, PROP_PERM_HW_ADDRESS,
g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_SPEED,
g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "",

View File

@ -33,7 +33,6 @@ G_BEGIN_DECLS
#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET))
#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass))
#define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address"
#define NM_DEVICE_ETHERNET_SPEED "speed"
#define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels"

View File

@ -92,10 +92,10 @@ typedef struct {
* @connection: the #NMConnection to return the parent name for, if supported
*
* Given a connection, returns the a parent interface name, parent connection
* UUID, or parent device hardware address for @connection.
* UUID, or parent device permanent hardware address for @connection.
*
* Returns: the parent interface name, parent connection UUID, parent
* device hardware address, or %NULL
* device permenent hardware address, or %NULL
*/
const char * (*get_connection_parent) (NMDeviceFactory *factory,
NMConnection *connection);

View File

@ -147,10 +147,15 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (nm_device_is_real (device)) {
const char *mac;
const char *hw_addr;
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
if (mac && !nm_utils_hwaddr_matches (mac, -1, nm_device_get_hw_address (device), -1))
return FALSE;
if (mac) {
hw_addr = nm_device_get_permanent_hw_address (device, TRUE);
if ( !hw_addr
|| !nm_utils_hwaddr_matches (mac, -1, hw_addr, -1))
return FALSE;
}
}
return TRUE;
@ -183,7 +188,7 @@ complete_connection (NMDevice *device,
}
setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband);
hw_address = nm_device_get_hw_address (device);
hw_address = nm_device_get_permanent_hw_address (device, TRUE);
if (setting_mac) {
/* Make sure the setting MAC (if any) matches the device's MAC */
if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) {
@ -209,7 +214,7 @@ static void
update_connection (NMDevice *device, NMConnection *connection)
{
NMSettingInfiniband *s_infiniband = nm_connection_get_setting_infiniband (connection);
const char *mac = nm_device_get_hw_address (device);
const char *mac = nm_device_get_permanent_hw_address (device, TRUE);
const char *transport_mode = "datagram";
int ifindex;

View File

@ -373,9 +373,8 @@ match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hw
if (!priv->parent)
return !fail_if_no_hwaddr;
parent_mac = nm_device_get_hw_address (priv->parent);
return nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE);
return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
}
static gboolean
@ -503,8 +502,6 @@ update_connection (NMDevice *device, NMConnection *connection)
static NMActStageReturn
act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
NMSettingWired *s_wired;
const char *cloned_mac;
NMActStageReturn ret;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@ -513,14 +510,9 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
return ret;
s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
if (s_wired) {
/* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW);
}
return TRUE;
if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE))
return NM_ACT_STAGE_RETURN_FAILURE;
return NM_ACT_STAGE_RETURN_SUCCESS;
}
static void
@ -549,16 +541,6 @@ realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
update_properties (device);
}
static void
deactivate (NMDevice *device)
{
/* Reset MAC address back to initial address */
if (nm_device_get_initial_hw_address (device)) {
nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device),
"reset", LOGD_DEVICE);
}
}
/******************************************************************/
static void
@ -639,7 +621,6 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
device_class->complete_connection = complete_connection;
device_class->connection_type = NM_SETTING_MACVLAN_SETTING_NAME;
device_class->create_and_realize = create_and_realize;
device_class->deactivate = deactivate;
device_class->get_generic_capabilities = get_generic_capabilities;
device_class->ip4_config_pre_commit = ip4_config_pre_commit;
device_class->is_available = is_available;

View File

@ -56,8 +56,9 @@ gboolean nm_device_bring_up (NMDevice *self, gboolean wait, gboolean *no_firmwar
void nm_device_take_down (NMDevice *self, gboolean block);
gboolean nm_device_set_hw_addr (NMDevice *device, const char *addr,
const char *detail, guint64 hw_log_domain);
gboolean nm_device_hw_addr_set (NMDevice *device, const char *addr, const char *detail);
gboolean nm_device_hw_addr_set_cloned (NMDevice *device, NMConnection *connection, gboolean is_wifi);
gboolean nm_device_hw_addr_reset (NMDevice *device, const char *detail);
void nm_device_set_firmware_missing (NMDevice *self, gboolean missing);
@ -107,6 +108,8 @@ void nm_device_queue_recheck_available (NMDevice *device,
void nm_device_set_wwan_ip4_config (NMDevice *device, NMIP4Config *config);
void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config);
gboolean nm_device_hw_addr_is_explict (NMDevice *device);
void nm_device_ip_method_failed (NMDevice *self, int family, NMDeviceStateReason reason);
gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value);

View File

@ -291,8 +291,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
{
NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
NMSettingWired *s_wired;
const char *cloned_mac;
NMActStageReturn ret;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@ -305,12 +303,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
if (g_strcmp0 (priv->mode, "tap"))
return NM_ACT_STAGE_RETURN_SUCCESS;
s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
if (s_wired) {
/* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
}
if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE))
return NM_ACT_STAGE_RETURN_FAILURE;
return NM_ACT_STAGE_RETURN_SUCCESS;
}

View File

@ -87,7 +87,6 @@ parent_hwaddr_maybe_changed (NMDevice *parent,
{
NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);
NMConnection *connection;
NMSettingWired *s_wired;
const char *new_mac, *old_mac;
NMSettingIPConfig *s_ip6;
@ -100,11 +99,8 @@ parent_hwaddr_maybe_changed (NMDevice *parent,
return;
/* Update the VLAN MAC only if configuration does not specify one */
s_wired = nm_connection_get_setting_wired (connection);
if (s_wired) {
if (nm_setting_wired_get_cloned_mac_address (s_wired))
return;
}
if (nm_device_hw_addr_is_explict (self))
return;
old_mac = nm_device_get_hw_address (self);
new_mac = nm_device_get_hw_address (parent);
@ -114,7 +110,7 @@ parent_hwaddr_maybe_changed (NMDevice *parent,
_LOGD (LOGD_VLAN, "parent hardware address changed to %s%s%s",
NM_PRINT_FMT_QUOTE_STRING (new_mac));
if (new_mac) {
nm_device_set_hw_addr (self, new_mac, "set", LOGD_VLAN);
nm_device_hw_addr_set (self, new_mac, "vlan-parent");
/* When changing the hw address the interface is taken down,
* removing the IPv6 configuration; reapply it.
*/
@ -378,21 +374,25 @@ match_parent (NMDeviceVlan *self, const char *parent)
static gboolean
match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr)
{
NMSettingWired *s_wired;
const char *setting_mac;
const char *device_mac;
NMDeviceVlanPrivate *priv;
NMSettingWired *s_wired;
const char *setting_mac;
const char *parent_mac;
s_wired = nm_connection_get_setting_wired (connection);
if (!s_wired)
return !fail_if_no_hwaddr;
s_wired = nm_connection_get_setting_wired (connection);
if (!s_wired)
return !fail_if_no_hwaddr;
setting_mac = nm_setting_wired_get_mac_address (s_wired);
if (!setting_mac)
return !fail_if_no_hwaddr;
setting_mac = nm_setting_wired_get_mac_address (s_wired);
if (!setting_mac)
return !fail_if_no_hwaddr;
device_mac = nm_device_get_hw_address (device);
priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
if (!priv->parent)
return !fail_if_no_hwaddr;
return nm_utils_hwaddr_matches (setting_mac, -1, device_mac, -1);
parent_mac = nm_device_get_permanent_hw_address (priv->parent, FALSE);
return parent_mac && nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1);
}
static gboolean
@ -550,8 +550,6 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
{
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (dev);
NMSettingVlan *s_vlan;
NMSettingWired *s_wired;
const char *cloned_mac;
NMActStageReturn ret;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@ -560,12 +558,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
return ret;
s_wired = (NMSettingWired *) nm_device_get_applied_setting (dev, NM_TYPE_SETTING_WIRED);
if (s_wired) {
/* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_VLAN);
}
if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE))
return NM_ACT_STAGE_RETURN_FAILURE;
/* Change MAC address to parent's one if needed */
if (priv->parent)
@ -619,14 +613,6 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
}
}
static void
deactivate (NMDevice *device)
{
/* Reset MAC address back to initial address */
if (nm_device_get_initial_hw_address (device))
nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_VLAN);
}
/******************************************************************/
static void
@ -690,7 +676,6 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
parent_class->bring_up = bring_up;
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
parent_class->deactivate = deactivate;
parent_class->is_available = is_available;
parent_class->notify_new_device_added = notify_new_device_added;

View File

@ -511,8 +511,6 @@ update_connection (NMDevice *device, NMConnection *connection)
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
{
NMSettingWired *s_wired;
const char *cloned_mac;
NMActStageReturn ret;
g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
@ -521,12 +519,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
return ret;
s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
if (s_wired) {
/* Set device MAC address if the connection wants to change it */
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE);
}
if (!nm_device_hw_addr_set_cloned (device, nm_device_get_applied_connection (device), FALSE))
return NM_ACT_STAGE_RETURN_FAILURE;
return NM_ACT_STAGE_RETURN_SUCCESS;
}

View File

@ -132,6 +132,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
PROP_IS_MASTER,
PROP_MASTER,
PROP_HW_ADDRESS,
PROP_PERM_HW_ADDRESS,
PROP_HAS_PENDING_ACTION,
PROP_METERED,
PROP_LLDP_NEIGHBORS,
@ -208,6 +209,13 @@ typedef struct {
NMIP4Config **configs;
} ArpingData;
typedef enum {
HW_ADDR_TYPE_UNSET = 0,
HW_ADDR_TYPE_PERMANENT,
HW_ADDR_TYPE_EXPLICIT,
HW_ADDR_TYPE_GENERATED,
} HwAddrType;
typedef struct _NMDevicePrivate {
bool in_state_changed;
@ -225,7 +233,12 @@ typedef struct _NMDevicePrivate {
char * udi;
char * iface; /* may change, could be renamed by user */
int ifindex;
guint hw_addr_len;
guint8 /*HwAddrType*/ hw_addr_type;
bool real;
char * ip_iface;
int ip_ifindex;
NMDeviceType type;
@ -237,13 +250,13 @@ typedef struct _NMDevicePrivate {
char * driver_version;
char * firmware_version;
RfKillType rfkill_type;
bool firmware_missing;
bool nm_plugin_missing;
bool firmware_missing:1;
bool nm_plugin_missing:1;
bool hw_addr_perm_fake:1; /* whether the permanent HW address could not be read and is a fake */
GHashTable * available_connections;
char * hw_addr;
guint hw_addr_len;
char * perm_hw_addr;
char * initial_hw_addr;
char * hw_addr_perm;
char * hw_addr_initial;
char * physical_port_id;
guint dev_id;
@ -616,6 +629,30 @@ _add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities)
/***********************************************************/
static const char *
_get_stable_id (NMConnection *connection, NMUtilsStableType *out_stable_type)
{
NMSettingConnection *s_con;
const char *stable_id;
nm_assert (NM_IS_CONNECTION (connection));
nm_assert (out_stable_type);
s_con = nm_connection_get_setting_connection (connection);
g_return_val_if_fail (s_con, NULL);
stable_id = nm_setting_connection_get_stable_id (s_con);
if (!stable_id) {
*out_stable_type = NM_UTILS_STABLE_TYPE_UUID;
return nm_connection_get_uuid (connection);
}
*out_stable_type = NM_UTILS_STABLE_TYPE_STABLE_ID;
return stable_id;
}
/***********************************************************/
const char *
nm_device_get_udi (NMDevice *self)
{
@ -1106,7 +1143,11 @@ nm_device_get_settings_connection (NMDevice *self)
NMConnection *
nm_device_get_applied_connection (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL;
}
@ -1123,23 +1164,12 @@ nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFla
}
NMSetting *
nm_device_get_applied_setting (NMDevice *device, GType setting_type)
nm_device_get_applied_setting (NMDevice *self, GType setting_type)
{
NMActRequest *req;
NMSetting *setting = NULL;
NMConnection *connection;
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
req = nm_device_get_act_request (device);
if (req) {
NMConnection *connection;
connection = nm_act_request_get_applied_connection (req);
if (connection)
setting = nm_connection_get_setting (connection, setting_type);
}
return setting;
connection = nm_device_get_applied_connection (self);
return connection ? nm_connection_get_setting (connection, setting_type) : NULL;
}
RfKillType
@ -1647,6 +1677,7 @@ device_link_changed (NMDevice *self)
int ifindex;
gboolean was_up;
gboolean update_unmanaged_specs = FALSE;
gboolean got_hw_addr = FALSE, had_hw_addr;
priv->device_link_changed_id = 0;
@ -1684,6 +1715,11 @@ device_link_changed (NMDevice *self)
_notify (self, PROP_DRIVER);
}
had_hw_addr = (priv->hw_addr != NULL);
nm_device_update_hw_address (self);
got_hw_addr = (!had_hw_addr && priv->hw_addr);
nm_device_update_permanent_hw_address (self);
if (info.name[0] && strcmp (priv->iface, info.name) != 0) {
_LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'",
priv->ifindex, priv->iface, info.name);
@ -1775,6 +1811,20 @@ device_link_changed (NMDevice *self)
if (update_unmanaged_specs)
nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings));
if ( got_hw_addr
&& !priv->up
&& nm_device_get_state (self) == NM_DEVICE_STATE_UNAVAILABLE) {
/*
* If the device is UNAVAILABLE, any previous try to
* bring it up probably has failed because of the
* invalid hardware address; try again.
*/
nm_device_bring_up (self, TRUE, NULL);
nm_device_queue_recheck_available (self,
NM_DEVICE_STATE_REASON_NONE,
NM_DEVICE_STATE_REASON_NONE);
}
return G_SOURCE_REMOVE;
}
@ -2123,6 +2173,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
nm_device_update_hw_address (self);
nm_device_update_initial_hw_address (self);
nm_device_update_permanent_hw_address (self);
/* Note: initial hardware address must be read before calling get_ignore_carrier() */
config = nm_config_get ();
@ -2308,6 +2359,7 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
_notify (self, PROP_UDI);
}
if (priv->hw_addr) {
priv->hw_addr_len = 0;
g_clear_pointer (&priv->hw_addr, g_free);
_notify (self, PROP_HW_ADDRESS);
}
@ -2316,8 +2368,10 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
_notify (self, PROP_PHYSICAL_PORT_ID);
}
g_clear_pointer (&priv->perm_hw_addr, g_free);
g_clear_pointer (&priv->initial_hw_addr, g_free);
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
g_clear_pointer (&priv->hw_addr_perm, g_free);
_notify (self, PROP_PERM_HW_ADDRESS);
g_clear_pointer (&priv->hw_addr_initial, g_free);
priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED;
if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
@ -3308,7 +3362,7 @@ nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave
static gboolean
nm_device_can_assume_connections (NMDevice *self)
{
return !!NM_DEVICE_GET_CLASS (self)->update_connection;
return !!NM_DEVICE_GET_CLASS (self)->update_connection;
}
/**
@ -3324,7 +3378,7 @@ nm_device_can_assume_connections (NMDevice *self)
* if there is no active connection or the active connection cannot be
* assumed.
*/
gboolean
static gboolean
nm_device_can_assume_active_connection (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@ -3371,6 +3425,45 @@ nm_device_can_assume_active_connection (NMDevice *self)
return TRUE;
}
static gboolean
unmanaged_on_quit (NMDevice *self)
{
/* Leave certain devices alone when quitting so their configuration
* can be taken over when NM restarts. This ensures connectivity while
* NM is stopped.
*/
if (nm_device_uses_assumed_connection (self)) {
/* An assume connection must be left alone */
return FALSE;
}
if (!nm_device_get_act_request (self)) {
/* a device without any active connection is either UNAVAILABLE or DISCONNECTED
* state. Since we don't know whether the device was upped by NetworkManager,
* we must leave it up on exit.
*/
return FALSE;
}
if (!nm_platform_link_can_assume (NM_PLATFORM_GET, nm_device_get_ifindex (self))) {
/* The device has no layer 3 configuration. Leave it up. */
return FALSE;
}
if (nm_device_can_assume_active_connection (self))
return FALSE;
return TRUE;
}
gboolean
nm_device_unmanage_on_quit (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
return NM_DEVICE_GET_CLASS (self)->unmanaged_on_quit (self);
}
static gboolean
nm_device_emit_recheck_assume (gpointer user_data)
{
@ -5859,11 +5952,17 @@ check_and_add_ipv6ll_addr (NMDevice *self)
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr,
nm_device_get_iface (self),
nm_connection_get_uuid (connection),
priv->linklocal6_dad_counter++,
&error)) {
NMUtilsStableType stable_type;
const char *stable_id;
stable_id = _get_stable_id (connection, &stable_type);
if ( !stable_id
|| !nm_utils_ipv6_addr_set_stable_privacy (stable_type,
&lladdr,
nm_device_get_iface (self),
stable_id,
priv->linklocal6_dad_counter++,
&error)) {
_LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
g_clear_error (&error);
linklocal6_failed (self);
@ -6205,6 +6304,8 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
NMActStageReturn ret;
NMSettingIP6Config *s_ip6 = NULL;
GError *error = NULL;
NMUtilsStableType stable_type;
const char *stable_id;
connection = nm_device_get_applied_connection (self);
g_assert (connection);
@ -6218,12 +6319,16 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
g_assert (s_ip6);
priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
nm_device_get_ip_ifindex (self),
nm_device_get_ip_iface (self),
nm_connection_get_uuid (connection),
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
&error);
stable_id = _get_stable_id (connection, &stable_type);
if (stable_id) {
priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
nm_device_get_ip_ifindex (self),
nm_device_get_ip_iface (self),
stable_type,
stable_id,
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
&error);
}
if (!priv->rdisc) {
_LOGE (LOGD_IP6, "addrconf6: failed to start router discovery: %s", error->message);
g_error_free (error);
@ -10548,6 +10653,8 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0");
}
nm_device_hw_addr_reset (self, "deactivate");
/* Call device type-specific deactivation */
if (NM_DEVICE_GET_CLASS (self)->deactivate)
NM_DEVICE_GET_CLASS (self)->deactivate (self);
@ -10622,6 +10729,8 @@ nm_device_spawn_iface_helper (NMDevice *self)
GPtrArray *argv;
gs_free char *dhcp4_address = NULL;
char *logging_backend;
NMUtilsStableType stable_type;
const char *stable_id;
if (priv->state != NM_DEVICE_STATE_ACTIVATED)
return;
@ -10640,6 +10749,12 @@ nm_device_spawn_iface_helper (NMDevice *self)
g_ptr_array_add (argv, g_strdup ("--uuid"));
g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection)));
stable_id = _get_stable_id (connection, &stable_type);
if (stable_id && stable_type != NM_UTILS_STABLE_TYPE_UUID) {
g_ptr_array_add (argv, g_strdup ("--stable-id"));
g_ptr_array_add (argv, g_strdup_printf ("%d %s", (int) stable_type, stable_id));
}
logging_backend = nm_config_get_is_debug (nm_config_get ())
? g_strdup ("debug")
: nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG,
@ -10935,6 +11050,7 @@ _set_state_full (NMDevice *self,
if (nm_device_get_act_request (self))
nm_device_cleanup (self, reason, CLEANUP_TYPE_DECONFIGURE);
nm_device_take_down (self, TRUE);
nm_device_hw_addr_reset (self, "unmanage");
set_nm_ipv6ll (self, FALSE);
restore_ip6_properties (self);
}
@ -10982,6 +11098,9 @@ _set_state_full (NMDevice *self,
}
}
break;
case NM_DEVICE_STATE_PREPARE:
nm_device_update_initial_hw_address (self);
break;
case NM_DEVICE_STATE_NEED_AUTH:
if (old_state > NM_DEVICE_STATE_NEED_AUTH) {
/* Clean up any half-done IP operations if the device's layer2
@ -11300,23 +11419,26 @@ nm_device_get_hw_address (NMDevice *self)
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
priv = NM_DEVICE_GET_PRIVATE (self);
return priv->hw_addr_len ? priv->hw_addr : NULL;
nm_assert ((!priv->hw_addr) ^ (priv->hw_addr_len > 0));
return priv->hw_addr;
}
void
nm_device_update_hw_address (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
int ifindex = nm_device_get_ifindex (self);
NMDevicePrivate *priv;
const guint8 *hwaddr;
gsize hwaddrlen = 0;
if (ifindex <= 0)
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->ifindex <= 0)
return;
hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddrlen);
hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen);
if ( priv->type == NM_DEVICE_TYPE_ETHERNET
&& hwaddr
&& nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth)))
hwaddrlen = 0;
@ -11326,17 +11448,28 @@ nm_device_update_hw_address (NMDevice *self)
g_free (priv->hw_addr);
priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen);
_LOGD (LOGD_HW | LOGD_DEVICE, "hardware address now %s", priv->hw_addr);
_LOGD (LOGD_HW | LOGD_DEVICE, "hw-addr: hardware address now %s", priv->hw_addr);
_notify (self, PROP_HW_ADDRESS);
if ( !priv->hw_addr_initial
|| ( priv->hw_addr_type == HW_ADDR_TYPE_UNSET
&& priv->state < NM_DEVICE_STATE_PREPARE
&& !nm_device_is_activating (self))) {
/* when we get a hw_addr the first time or while the device
* is not activated (with no explict hw address set), always
* update our inital hw-address as well. */
nm_device_update_initial_hw_address (self);
}
}
} else {
/* Invalid or no hardware address */
if (priv->hw_addr_len != 0) {
g_clear_pointer (&priv->hw_addr, g_free);
priv->hw_addr_len = 0;
_LOGD (LOGD_HW | LOGD_DEVICE,
"previous hardware address is no longer valid");
_notify (self, PROP_HW_ADDRESS);
"hw-addr: failed reading current MAC address (stay with %s)",
priv->hw_addr);
} else {
_LOGD (LOGD_HW | LOGD_DEVICE,
"hw-addr: failed reading current MAC address");
}
}
}
@ -11346,84 +11479,361 @@ nm_device_update_initial_hw_address (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->hw_addr_len) {
priv->initial_hw_addr = g_strdup (priv->hw_addr);
_LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr);
if (priv->ifindex > 0) {
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
size_t len = 0;
if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) {
g_warn_if_fail (len == priv->hw_addr_len);
priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
_LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s",
priv->perm_hw_addr);
} else {
/* Fall back to current address */
_LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address");
priv->perm_hw_addr = g_strdup (priv->hw_addr);
}
if ( priv->hw_addr
&& !nm_streq0 (priv->hw_addr_initial, priv->hw_addr)) {
if ( priv->hw_addr_initial
&& priv->hw_addr_type != HW_ADDR_TYPE_UNSET) {
/* once we have the initial hw address set, we only allow
* update if the currenty type is "unset". */
return;
}
g_free (priv->hw_addr_initial);
priv->hw_addr_initial = g_strdup (priv->hw_addr);
_LOGD (LOGD_DEVICE, "hw-addr: update initial MAC address %s",
priv->hw_addr_initial);
}
}
gboolean
nm_device_set_hw_addr (NMDevice *self, const char *addr,
const char *detail, guint64 hw_log_domain)
void
nm_device_update_permanent_hw_address (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
gboolean success = FALSE;
const char *cur_addr = nm_device_get_hw_address (self);
guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
size_t len = 0;
gboolean success_read;
/* Fall back to the permanent address */
if (!addr)
addr = priv->perm_hw_addr;
if (!addr)
return FALSE;
if (priv->hw_addr_perm) {
/* the permanent hardware address is only read once and not
* re-read later.
*
* Except during unrealize/realize cycles, where we clear the permanent
* hardware address during unrealization. */
return;
}
if (priv->ifindex <= 0)
return;
if (!priv->hw_addr_len) {
nm_device_update_hw_address (self);
if (!priv->hw_addr_len)
return;
}
success_read = nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len);
if (!success_read || len != priv->hw_addr_len) {
/* Fall back to current address. We use the fake address and keep it
* until the device unrealizes.
*
* In some cases it might be necessary to know whether this is a "real" or
* a temporary address (fake). */
_LOGD (LOGD_HW | LOGD_ETHER, "hw-addr: %s (use current: %s)",
success_read
? "unable to read permanent MAC address"
: "read HW addr length of permanent MAC address differs",
priv->hw_addr);
priv->hw_addr_perm_fake = TRUE;
priv->hw_addr_perm = g_strdup (priv->hw_addr);
} else {
priv->hw_addr_perm_fake = FALSE;
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, len);
_LOGD (LOGD_DEVICE, "hw-addr: read permanent MAC address '%s'",
priv->hw_addr_perm);
}
_notify (self, PROP_PERM_HW_ADDRESS);
}
static const char *
_get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_addr)
{
NMSetting *setting;
const char *addr = NULL;
nm_assert (out_addr && !*out_addr);
setting = nm_connection_get_setting (connection,
is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
if (setting) {
addr = is_wifi
? nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) setting)
: nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) setting);
}
if (!addr) {
gs_free char *a = NULL;
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
is_wifi ? "wifi.cloned-mac-address" : "ethernet.cloned-mac-address",
self);
/* default is permanent. */
addr = NM_CLONED_MAC_PERMANENT;
if (!a) {
if (is_wifi) {
NMSettingMacRandomization v;
/* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
"wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION,
self);
v = _nm_utils_ascii_str_to_int64 (a, 10,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
addr = NM_CLONED_MAC_RANDOM;
}
} else if ( NM_CLONED_MAC_IS_SPECIAL (a)
|| nm_utils_hwaddr_valid (a, ETH_ALEN))
addr = *out_addr = g_steal_pointer (&a);
}
return addr;
}
static const char *
_get_generate_mac_address_mask_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_value)
{
NMSetting *setting;
const char *value = NULL;
char *a;
nm_assert (out_value && !*out_value);
setting = nm_connection_get_setting (connection,
is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
if (setting) {
value = is_wifi
? nm_setting_wireless_get_generate_mac_address_mask ((NMSettingWireless *) setting)
: nm_setting_wired_get_generate_mac_address_mask ((NMSettingWired *) setting);
if (value)
return value;
}
a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
is_wifi ? "wifi.generate-mac-address-mask" : "ethernet.generate-mac-mac-address-mask",
self);
if (!a)
return NULL;
*out_value = a;
return a;
}
gboolean
nm_device_hw_addr_is_explict (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
return !NM_IN_SET (priv->hw_addr_type, HW_ADDR_TYPE_PERMANENT, HW_ADDR_TYPE_UNSET);
}
static gboolean
_hw_addr_set (NMDevice *self,
const char *addr,
const char *operation,
const char *detail)
{
NMDevicePrivate *priv;
gboolean success = FALSE;
const char *cur_addr;
guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
guint hw_addr_len;
gboolean was_up;
nm_assert (NM_IS_DEVICE (self));
nm_assert (addr);
nm_assert (operation);
priv = NM_DEVICE_GET_PRIVATE (self);
cur_addr = nm_device_get_hw_address (self);
/* Do nothing if current MAC is same */
if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
_LOGD (LOGD_DEVICE | hw_log_domain, "no MAC address change needed");
_LOGD (LOGD_DEVICE, "set-hw-addr: no MAC address change needed");
return TRUE;
}
if (!nm_utils_hwaddr_aton (addr, addr_bytes, priv->hw_addr_len)) {
_LOGW (LOGD_DEVICE | hw_log_domain, "invalid MAC address %s", addr);
return FALSE;
hw_addr_len = priv->hw_addr_len;
if (!hw_addr_len)
hw_addr_len = _nm_utils_hwaddr_length (addr);
if ( !hw_addr_len
|| !nm_utils_hwaddr_aton (addr, addr_bytes, hw_addr_len))
g_return_val_if_reached (FALSE);
_LOGT (LOGD_DEVICE, "set-hw-addr: setting MAC address to '%s' (%s, %s)...", addr, operation, detail);
was_up = nm_device_is_up (self);
if (was_up) {
/* Can't change MAC address while device is up */
nm_device_take_down (self, FALSE);
}
/* Can't change MAC address while device is up */
nm_device_take_down (self, FALSE);
success = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, priv->hw_addr_len);
success = nm_platform_link_set_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), addr_bytes, hw_addr_len);
if (success) {
/* MAC address succesfully changed; update the current MAC to match */
nm_device_update_hw_address (self);
cur_addr = nm_device_get_hw_address (self);
if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
_LOGI (LOGD_DEVICE | hw_log_domain, "%s MAC address to %s",
detail, addr);
_LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
operation, addr, detail);
} else {
_LOGW (LOGD_DEVICE | hw_log_domain,
"new MAC address %s not successfully set", addr);
_LOGW (LOGD_DEVICE,
"set-hw-addr: new MAC address %s not successfully set to %s (%s)",
addr, operation, detail);
success = FALSE;
}
} else {
_LOGW (LOGD_DEVICE | hw_log_domain, "failed to %s MAC address to %s",
detail, addr);
_LOGW (LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s)",
operation, addr, detail);
}
if (was_up) {
if (!nm_device_bring_up (self, TRUE, NULL))
return FALSE;
}
nm_device_bring_up (self, TRUE, NULL);
return success;
}
const char *
nm_device_get_permanent_hw_address (NMDevice *self)
gboolean
nm_device_hw_addr_set (NMDevice *self, const char *addr, const char *detail)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
if (!addr)
g_return_val_if_reached (FALSE);
/* this is called by NMDeviceVlan to take the MAC address from the parent
* and by NMDeviceWifi to set a random MAC address during scanning.
* In this case, it's like setting it to PERMANENT. */
priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT;
return _hw_addr_set (self, addr, "set", detail);
}
gboolean
nm_device_hw_addr_set_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi)
{
NMDevicePrivate *priv;
gs_free char *hw_addr_tmp = NULL;
gs_free char *hw_addr_generated = NULL;
gs_free char *generate_mac_address_mask_tmp = NULL;
const char *addr, *addr_setting;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
if (!connection)
g_return_val_if_reached (FALSE);
addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &hw_addr_tmp);
if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) {
/* "preserve" means to reset the initial MAC address. */
return nm_device_hw_addr_reset (self, addr_setting);
}
if (nm_streq (addr, NM_CLONED_MAC_PERMANENT)) {
addr = nm_device_get_permanent_hw_address (self, TRUE);
if (!addr)
return FALSE;
priv->hw_addr_type = HW_ADDR_TYPE_PERMANENT;
} else if (NM_IN_STRSET (addr, NM_CLONED_MAC_RANDOM)) {
if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) {
/* hm, we already use a generate MAC address. Most certainly, that is from the same
* activation request, so we should not create a new random address, instead keep
* the current. */
return TRUE;
}
hw_addr_generated = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (self),
_get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp));
if (!hw_addr_generated) {
_LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "random");
return FALSE;
}
priv->hw_addr_type = HW_ADDR_TYPE_GENERATED;
addr = hw_addr_generated;
} else if (NM_IN_STRSET (addr, NM_CLONED_MAC_STABLE)) {
NMUtilsStableType stable_type;
const char *stable_id;
if (priv->hw_addr_type == HW_ADDR_TYPE_GENERATED) {
/* hm, we already use a generate MAC address. Most certainly, that is from the same
* activation request, so let's skip creating the stable address anew. */
return TRUE;
}
stable_id = _get_stable_id (connection, &stable_type);
if (stable_id) {
hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id,
nm_device_get_ip_iface (self),
nm_device_get_initial_hw_address (self),
_get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp));
}
if (!hw_addr_generated) {
_LOGW (LOGD_DEVICE, "set-hw-addr: failed to generate %s MAC address", "stable");
return FALSE;
}
priv->hw_addr_type = HW_ADDR_TYPE_GENERATED;
addr = hw_addr_generated;
} else {
/* this must be a valid address. Otherwise, we shouldn't come here. */
if (_nm_utils_hwaddr_length (addr) <= 0) {
g_return_val_if_reached (FALSE);
}
priv->hw_addr_type = HW_ADDR_TYPE_EXPLICIT;
}
return _hw_addr_set (self, addr, "set-cloned", addr_setting);
}
gboolean
nm_device_hw_addr_reset (NMDevice *self, const char *detail)
{
NMDevicePrivate *priv;
const char *addr;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->hw_addr_type == HW_ADDR_TYPE_UNSET)
return TRUE;
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
addr = nm_device_get_initial_hw_address (self);
if (!addr) {
/* as hw_addr_type is not UNSET, we expect that we can get an
* initial address to which to reset. */
g_return_val_if_reached (FALSE);
}
return _hw_addr_set (self, addr, "reset", detail);
}
const char *
nm_device_get_permanent_hw_address (NMDevice *self, gboolean fallback_fake)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
return NM_DEVICE_GET_PRIVATE (self)->perm_hw_addr;
priv = NM_DEVICE_GET_PRIVATE (self);
if (!priv->hw_addr_perm)
return NULL;
if ( priv->hw_addr_perm_fake
&& !fallback_fake)
return NULL;
return priv->hw_addr_perm;
}
const char *
@ -11431,7 +11841,7 @@ nm_device_get_initial_hw_address (NMDevice *self)
{
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
return NM_DEVICE_GET_PRIVATE (self)->initial_hw_addr;
return NM_DEVICE_GET_PRIVATE (self)->hw_addr_initial;
}
/**
@ -11469,9 +11879,9 @@ nm_device_spec_match_list (NMDevice *self, const GSList *specs)
static NMMatchSpecMatchType
spec_match_list (NMDevice *self, const GSList *specs)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
const GSList *iter;
const char *hw_addr_perm;
for (iter = specs; iter; iter = g_slist_next (iter)) {
if (!strcmp ((const char *) iter->data, "*")) {
@ -11479,8 +11889,10 @@ spec_match_list (NMDevice *self, const GSList *specs)
break;
}
}
if (priv->hw_addr_len && priv->hw_addr) {
m = nm_match_spec_hwaddr (specs, priv->hw_addr);
hw_addr_perm = nm_device_get_permanent_hw_address (self, FALSE);
if (hw_addr_perm) {
m = nm_match_spec_hwaddr (specs, hw_addr_perm);
matched = MAX (matched, m);
}
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
@ -11563,7 +11975,8 @@ constructor (GType type,
self = NM_DEVICE (object);
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->iface) {
if ( priv->iface
&& G_LIKELY (!nm_utils_get_testing ())) {
pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) {
@ -11572,6 +11985,17 @@ constructor (GType type,
}
}
if (priv->hw_addr_perm) {
priv->hw_addr_len = _nm_utils_hwaddr_length (priv->hw_addr_perm);
if (!priv->hw_addr_len) {
g_clear_pointer (&priv->hw_addr_perm, g_free);
g_return_val_if_reached (object);
}
priv->hw_addr = g_strdup (priv->hw_addr_perm);
_LOGT (LOGD_DEVICE, "hw-addr: has permanent hw-address '%s'", priv->hw_addr_perm);
}
return object;
}
@ -11697,8 +12121,8 @@ finalize (GObject *object)
_LOGD (LOGD_DEVICE, "finalize(): %s", G_OBJECT_TYPE_NAME (self));
g_free (priv->hw_addr);
g_free (priv->perm_hw_addr);
g_free (priv->initial_hw_addr);
g_free (priv->hw_addr_perm);
g_free (priv->hw_addr_initial);
g_slist_free_full (priv->pending_actions, g_free);
g_slist_free_full (priv->dad6_failed_addrs, g_free);
g_clear_pointer (&priv->physical_port_id, g_free);
@ -11727,10 +12151,8 @@ static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDevice *self = NM_DEVICE (object);
NMDevice *self = (NMDevice *) object;
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
const char *hw_addr, *p;
guint count;
switch (prop_id) {
case PROP_UDI:
@ -11808,32 +12230,9 @@ set_property (GObject *object, guint prop_id,
case PROP_IS_MASTER:
priv->is_master = g_value_get_boolean (value);
break;
case PROP_HW_ADDRESS:
case PROP_PERM_HW_ADDRESS:
/* construct only */
p = hw_addr = g_value_get_string (value);
/* Hardware address length is the number of ':' plus 1 */
count = 1;
while (p && *p) {
if (*p++ == ':')
count++;
}
if (count < ETH_ALEN || count > NM_UTILS_HWADDR_LEN_MAX) {
if (hw_addr && *hw_addr) {
_LOGW (LOGD_DEVICE, "ignoring hardware address '%s' with unexpected length %d",
hw_addr, count);
}
break;
}
priv->hw_addr_len = count;
g_free (priv->hw_addr);
if (nm_utils_hwaddr_valid (hw_addr, priv->hw_addr_len))
priv->hw_addr = g_strdup (hw_addr);
else {
_LOGW (LOGD_DEVICE, "could not parse hw-address '%s'", hw_addr);
priv->hw_addr = NULL;
}
priv->hw_addr_perm = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -11956,6 +12355,10 @@ get_property (GObject *object, guint prop_id,
case PROP_HW_ADDRESS:
g_value_set_string (value, priv->hw_addr);
break;
case PROP_PERM_HW_ADDRESS:
/* this property is exposed on D-Bus for NMDeviceEthernet and NMDeviceWifi. */
g_value_set_string (value, nm_device_get_permanent_hw_address (self, FALSE));
break;
case PROP_HAS_PENDING_ACTION:
g_value_set_boolean (value, nm_device_has_pending_action (self));
break;
@ -12041,6 +12444,7 @@ nm_device_class_init (NMDeviceClass *klass)
klass->take_down = take_down;
klass->carrier_changed = carrier_changed;
klass->get_ip_iface_identifier = get_ip_iface_identifier;
klass->unmanaged_on_quit = unmanaged_on_quit;
/* Properties */
obj_properties[PROP_UDI] =
@ -12198,6 +12602,11 @@ nm_device_class_init (NMDeviceClass *klass)
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_HW_ADDRESS] =
g_param_spec_string (NM_DEVICE_HW_ADDRESS, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_PERM_HW_ADDRESS] =
g_param_spec_string (NM_DEVICE_PERM_HW_ADDRESS, "", "",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);

View File

@ -57,6 +57,11 @@
#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
#define NM_DEVICE_MTU "mtu"
#define NM_DEVICE_HW_ADDRESS "hw-address"
/* "perm-hw-address" is exposed on D-Bus both for NMDeviceEthernet
* and NMDeviceWifi. */
#define NM_DEVICE_PERM_HW_ADDRESS "perm-hw-address"
#define NM_DEVICE_METERED "metered"
#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors"
#define NM_DEVICE_REAL "real"
@ -323,6 +328,8 @@ typedef struct {
gboolean (* owns_iface) (NMDevice *self, const char *iface);
NMConnection * (* new_default_connection) (NMDevice *self);
gboolean (* unmanaged_on_quit) (NMDevice *self);
} NMDeviceClass;
typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
@ -353,7 +360,8 @@ guint32 nm_device_get_ip4_route_metric (NMDevice *dev);
guint32 nm_device_get_ip6_route_metric (NMDevice *dev);
const char * nm_device_get_hw_address (NMDevice *dev);
const char * nm_device_get_permanent_hw_address (NMDevice *dev);
const char * nm_device_get_permanent_hw_address (NMDevice *dev,
gboolean fallback_fake);
const char * nm_device_get_initial_hw_address (NMDevice *dev);
NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev);
@ -411,7 +419,7 @@ gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnec
gboolean nm_device_uses_assumed_connection (NMDevice *device);
gboolean nm_device_can_assume_active_connection (NMDevice *device);
gboolean nm_device_unmanage_on_quit (NMDevice *self);
gboolean nm_device_spec_match_list (NMDevice *device, const GSList *specs);
@ -578,6 +586,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device,
void nm_device_update_hw_address (NMDevice *self);
void nm_device_update_initial_hw_address (NMDevice *self);
void nm_device_update_permanent_hw_address (NMDevice *self);
void nm_device_update_dynamic_ip_setup (NMDevice *self);
G_END_DECLS

View File

@ -62,6 +62,8 @@ _LOG_DECLARE_SELF(NMDeviceWifi);
#define SCAN_INTERVAL_STEP 20
#define SCAN_INTERVAL_MAX 120
#define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5
#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries"
G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
@ -71,7 +73,6 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
enum {
PROP_0,
PROP_PERM_HW_ADDRESS,
PROP_MODE,
PROP_BITRATE,
PROP_ACCESS_POINTS,
@ -120,6 +121,9 @@ struct _NMDeviceWifiPrivate {
guint reacquire_iface_id;
NMDeviceWifiCapabilities capabilities;
gint32 hw_addr_scan_expire;
char *hw_addr_scan;
};
static gboolean check_scanning_allowed (NMDeviceWifi *self);
@ -170,6 +174,8 @@ static void ap_add_remove (NMDeviceWifi *self,
static void remove_supplicant_interface_error_handler (NMDeviceWifi *self);
static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset);
/*****************************************************************/
static void
@ -187,6 +193,18 @@ constructed (GObject *object)
priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ());
}
static gboolean
unmanaged_on_quit (NMDevice *self)
{
/* Wi-Fi devices cannot be assumed and are always taken down.
* However, also when being disconnected, we scan and thus
* set the MAC address to a random value.
*
* We must restore the original MAC address when quitting, thus
* signal to unmanage the device. */
return TRUE;
}
static gboolean
supplicant_interface_acquire (NMDeviceWifi *self)
{
@ -403,14 +421,6 @@ periodic_update_cb (gpointer user_data)
return TRUE;
}
static void
realize_start_notify (NMDevice *device, const NMPlatformLink *plink)
{
NM_DEVICE_CLASS (nm_device_wifi_parent_class)->realize_start_notify (device, plink);
g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
}
static gboolean
bring_up (NMDevice *device, gboolean *no_firmware)
{
@ -491,9 +501,8 @@ deactivate (NMDevice *device)
/* Clear any critical protocol notification in the Wi-Fi stack */
nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE);
/* Reset MAC address back to initial address */
if (nm_device_get_initial_hw_address (device))
nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI);
g_clear_pointer (&priv->hw_addr_scan, g_free);
_hw_addr_set_scanning (self, TRUE);
/* Ensure we're in infrastructure mode after deactivation; some devices
* (usually older ones) don't scan well in adhoc mode.
@ -572,7 +581,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
if (!s_wireless)
return FALSE;
perm_hw_addr = nm_device_get_permanent_hw_address (device);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
mac = nm_setting_wireless_get_mac_address (s_wireless);
if (perm_hw_addr) {
if (mac && !nm_utils_hwaddr_matches (mac, -1, perm_hw_addr, -1))
@ -685,35 +694,31 @@ check_connection_available (NMDevice *device,
return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE);
}
/*
* List of manufacturer default SSIDs that are often unchanged by users.
*
* NOTE: this list should *not* contain networks that you would like to
* automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot".
*/
static const char *
manf_defaults[] = {
"linksys",
"linksys-a",
"linksys-g",
"default",
"belkin54g",
"NETGEAR",
"o2DSL",
"WLAN",
"ALICE-WLAN",
"Speedport W 501V",
"TURBONETT",
};
#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0]))
static gboolean
is_manf_default_ssid (const GByteArray *ssid)
{
int i;
/*
* List of manufacturer default SSIDs that are often unchanged by users.
*
* NOTE: this list should *not* contain networks that you would like to
* automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot".
*/
static const char *manf_defaults[] = {
"linksys",
"linksys-a",
"linksys-g",
"default",
"belkin54g",
"NETGEAR",
"o2DSL",
"WLAN",
"ALICE-WLAN",
"Speedport W 501V",
"TURBONETT",
};
for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) {
for (i = 0; i < G_N_ELEMENTS (manf_defaults); i++) {
if (ssid->len == strlen (manf_defaults[i])) {
if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0)
return TRUE;
@ -868,7 +873,7 @@ complete_connection (NMDevice *device,
if (hidden)
g_object_set (s_wifi, NM_SETTING_WIRELESS_HIDDEN, TRUE, NULL);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
if (perm_hw_addr) {
setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
if (setting_mac) {
@ -1027,6 +1032,60 @@ impl_device_wifi_get_all_access_points (NMDeviceWifi *self,
g_ptr_array_unref (paths);
}
static void
_hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset)
{
NMDevice *device = (NMDevice *) self;
NMDeviceWifiPrivate *priv;
guint32 now;
gboolean randomize;
g_return_if_fail (NM_IS_DEVICE_WIFI (self));
if ( nm_device_is_activating (device)
|| nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED)
return;
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
randomize = nm_config_data_get_device_config_boolean (NM_CONFIG_GET_DATA,
"wifi.scan-rand-mac-address",
device,
TRUE, TRUE);
if (!randomize) {
g_clear_pointer (&priv->hw_addr_scan, g_free);
if (do_reset)
nm_device_hw_addr_reset (device, "scanning");
return;
}
now = nm_utils_get_monotonic_timestamp_s ();
if ( !priv->hw_addr_scan
|| now >= priv->hw_addr_scan_expire) {
gs_free char *generate_mac_address_mask = NULL;
/* the random MAC address for scanning expires after a while.
*
* We don't bother with to update the MAC address exactly when
* it expires, instead on the next scan request, we will generate
* a new one.*/
priv->hw_addr_scan_expire = now + (SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN * 60);
generate_mac_address_mask = nm_config_data_get_device_config (NM_CONFIG_GET_DATA,
"wifi.scan-generate-mac-address-mask",
device,
NULL);
g_free (priv->hw_addr_scan);
priv->hw_addr_scan = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (device),
generate_mac_address_mask);
}
nm_device_hw_addr_set (device, priv->hw_addr_scan, "scanning");
}
static void
request_scan_cb (NMDevice *device,
GDBusMethodInvocation *context,
@ -1336,6 +1395,8 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
_LOGD (LOGD_WIFI_SCAN, "no SSIDs to probe scan");
}
_hw_addr_set_scanning (self, FALSE);
if (nm_supplicant_interface_request_scan (priv->sup_iface, ssids)) {
/* success */
backoff = TRUE;
@ -2210,9 +2271,6 @@ build_supplicant_config (NMDeviceWifi *self,
NMSupplicantConfig *config = NULL;
NMSettingWireless *s_wireless;
NMSettingWirelessSecurity *s_wireless_sec;
NMSupplicantFeature mac_randomization_support;
NMSettingMacRandomization mac_randomization_fallback;
gs_free char *svalue = NULL;
g_return_val_if_fail (priv->sup_iface, NULL);
@ -2227,20 +2285,9 @@ build_supplicant_config (NMDeviceWifi *self,
_LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out.");
}
mac_randomization_support = nm_supplicant_interface_get_mac_randomization_support (priv->sup_iface);
svalue = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
"wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION,
NM_DEVICE (self));
mac_randomization_fallback = _nm_utils_ascii_str_to_int64 (svalue, 10,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
if (!nm_supplicant_config_add_setting_wireless (config,
s_wireless,
fixed_freq,
mac_randomization_support,
mac_randomization_fallback,
error)) {
g_prefix_error (error, "802-11-wireless: ");
goto error;
@ -2290,7 +2337,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
NMActRequest *req;
NMConnection *connection;
NMSettingWireless *s_wireless;
const char *cloned_mac;
const char *mode;
const char *ap_path;
@ -2330,9 +2376,12 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
return NM_ACT_STAGE_RETURN_FAILURE;
}
/* forget the temporary MAC address used during scanning */
g_clear_pointer (&priv->hw_addr_scan, g_free);
/* Set spoof MAC to the interface */
cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_WIFI);
if (!nm_device_hw_addr_set_cloned (device, connection, TRUE))
return NM_ACT_STAGE_RETURN_FAILURE;
/* AP mode never uses a specific object or existing scanned AP */
if (priv->mode != NM_802_11_MODE_AP) {
@ -2972,6 +3021,8 @@ finalize (GObject *object)
g_hash_table_unref (priv->aps);
g_free (priv->hw_addr_scan);
G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
}
@ -2986,9 +3037,6 @@ get_property (GObject *object, guint prop_id,
GPtrArray *array;
switch (prop_id) {
case PROP_PERM_HW_ADDRESS:
g_value_set_string (value, nm_device_get_permanent_hw_address (NM_DEVICE (device)));
break;
case PROP_MODE:
g_value_set_uint (value, priv->mode);
break;
@ -3053,7 +3101,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
object_class->dispose = dispose;
object_class->finalize = finalize;
parent_class->realize_start_notify = realize_start_notify;
parent_class->bring_up = bring_up;
parent_class->can_auto_connect = can_auto_connect;
parent_class->is_available = is_available;
@ -3070,19 +3117,13 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
parent_class->deactivate = deactivate;
parent_class->unmanaged_on_quit = unmanaged_on_quit;
parent_class->state_changed = device_state_changed;
klass->scanning_allowed = scanning_allowed;
/* Properties */
g_object_class_install_property
(object_class, PROP_PERM_HW_ADDRESS,
g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property
(object_class, PROP_MODE,
g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "",

View File

@ -36,7 +36,6 @@ G_BEGIN_DECLS
#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI))
#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass))
#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address"
#define NM_DEVICE_WIFI_MODE "mode"
#define NM_DEVICE_WIFI_BITRATE "bitrate"
#define NM_DEVICE_WIFI_ACCESS_POINTS "access-points"

View File

@ -40,7 +40,7 @@ typedef struct {
gboolean has;
GSList *spec;
} match_device;
} ConnectionInfo;
} MatchSectionInfo;
typedef struct {
char *config_main_file;
@ -52,7 +52,11 @@ typedef struct {
/* A zero-terminated list of pre-processed information from the
* [connection] sections. This is to speed up lookup. */
ConnectionInfo *connection_infos;
MatchSectionInfo *connection_infos;
/* A zero-terminated list of pre-processed information from the
* [device] sections. This is to speed up lookup. */
MatchSectionInfo *device_infos;
struct {
char *uri;
@ -268,9 +272,16 @@ nm_config_data_get_rc_manager (const NMConfigData *self)
gboolean
nm_config_data_get_ignore_carrier (const NMConfigData *self, NMDevice *device)
{
gs_free char *value = NULL;
gboolean has_match;
g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
value = nm_config_data_get_device_config (self, NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER, device, &has_match);
if (has_match)
return nm_config_parse_boolean (value, FALSE);
return nm_device_spec_match_list (device, NM_CONFIG_DATA_GET_PRIVATE (self)->ignore_carrier);
}
@ -451,6 +462,7 @@ static int
_nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy)
{
gboolean a_is_connection, b_is_connection;
gboolean a_is_device, b_is_device;
gboolean a_is_intern, b_is_intern;
const char *a = *pa;
const char *b = *pb;
@ -488,6 +500,28 @@ _nm_config_data_log_sort (const char **pa, const char **pb, gpointer dummy)
if (b_is_connection && !a_is_connection)
return -1;
/* we sort device groups before connection groups (to the end). */
a_is_device = a && g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE);
b_is_device = b && g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE);
if (a_is_device && b_is_device) {
/* if both are device groups, we want the explicit [device] group first. */
a_is_device = a[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE)] == '\0';
b_is_device = b[NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE)] == '\0';
if (a_is_device != b_is_device) {
if (a_is_device)
return -1;
return 1;
}
/* the sections are ordered lowest-priority first. Reverse their order. */
return pa < pb ? 1 : -1;
}
if (a_is_device && !b_is_device)
return 1;
if (b_is_device && !a_is_device)
return -1;
/* no reordering. */
return 0;
}
@ -1049,25 +1083,18 @@ global_dns_equal (NMGlobalDnsConfig *old, NMGlobalDnsConfig *new)
/************************************************************************/
char *
nm_config_data_get_connection_default (const NMConfigData *self,
const char *property,
NMDevice *device)
static const MatchSectionInfo *
_match_section_infos_lookup (const MatchSectionInfo *match_section_infos,
GKeyFile *keyfile,
const char *property,
NMDevice *device,
char **out_value)
{
NMConfigDataPrivate *priv;
const ConnectionInfo *connection_info;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (property && *property, NULL);
g_return_val_if_fail (strchr (property, '.'), NULL);
priv = NM_CONFIG_DATA_GET_PRIVATE (self);
if (!priv->connection_infos)
if (!match_section_infos)
return NULL;
for (connection_info = &priv->connection_infos[0]; connection_info->group_name; connection_info++) {
char *value;
for (; match_section_infos->group_name; match_section_infos++) {
char *value = NULL;
gboolean match;
/* FIXME: Here we use g_key_file_get_string(). This should be in sync with what keyfile-reader
@ -1077,23 +1104,87 @@ nm_config_data_get_connection_default (const NMConfigData *self,
* string_to_value(keyfile_to_string(keyfile)) in one. Optimally, keyfile library would
* expose both functions, and we would return here keyfile_to_string(keyfile).
* The caller then could convert the string to the proper value via string_to_value(value). */
value = g_key_file_get_string (priv->keyfile, connection_info->group_name, property, NULL);
if (!value && !connection_info->stop_match)
value = g_key_file_get_string (keyfile, match_section_infos->group_name, property, NULL);
if (!value && !match_section_infos->stop_match)
continue;
match = TRUE;
if (connection_info->match_device.has)
match = device && nm_device_spec_match_list (device, connection_info->match_device.spec);
if (match_section_infos->match_device.has)
match = device && nm_device_spec_match_list (device, match_section_infos->match_device.spec);
if (match)
return value;
if (match) {
*out_value = value;
return match_section_infos;
}
g_free (value);
}
return NULL;
}
char *
nm_config_data_get_device_config (const NMConfigData *self,
const char *property,
NMDevice *device,
gboolean *has_match)
{
NMConfigDataPrivate *priv;
const MatchSectionInfo *connection_info;
char *value = NULL;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (property && *property, NULL);
priv = NM_CONFIG_DATA_GET_PRIVATE (self);
connection_info = _match_section_infos_lookup (&priv->device_infos[0],
priv->keyfile,
property,
device,
&value);
NM_SET_OUT (has_match, !!connection_info);
return value;
}
gboolean
nm_config_data_get_device_config_boolean (const NMConfigData *self,
const char *property,
NMDevice *device,
gint val_no_match,
gint val_invalid)
{
gs_free char *value = NULL;
gboolean has_match;
value = nm_config_data_get_device_config (self, property, device, &has_match);
if (!has_match)
return val_no_match;
return nm_config_parse_boolean (value, val_invalid);
}
char *
nm_config_data_get_connection_default (const NMConfigData *self,
const char *property,
NMDevice *device)
{
NMConfigDataPrivate *priv;
char *value = NULL;
g_return_val_if_fail (self, NULL);
g_return_val_if_fail (property && *property, NULL);
g_return_val_if_fail (strchr (property, '.'), NULL);
priv = NM_CONFIG_DATA_GET_PRIVATE (self);
_match_section_infos_lookup (&priv->connection_infos[0],
priv->keyfile,
property,
device,
&value);
return value;
}
static void
_get_connection_info_init (ConnectionInfo *connection_info, GKeyFile *keyfile, char *group)
_get_connection_info_init (MatchSectionInfo *connection_info, GKeyFile *keyfile, char *group)
{
/* pass ownership of @group on... */
connection_info->group_name = group;
@ -1105,27 +1196,43 @@ _get_connection_info_init (ConnectionInfo *connection_info, GKeyFile *keyfile, c
connection_info->stop_match = nm_config_keyfile_get_boolean (keyfile, group, "stop-match", FALSE);
}
static ConnectionInfo *
_get_connection_infos (GKeyFile *keyfile)
static void
_match_section_infos_free (MatchSectionInfo *match_section_infos)
{
guint i;
if (!match_section_infos)
return;
for (i = 0; match_section_infos[i].group_name; i++) {
g_free (match_section_infos[i].group_name);
g_slist_free_full (match_section_infos[i].match_device.spec, g_free);
}
g_free (match_section_infos);
}
static MatchSectionInfo *
_match_section_infos_construct (GKeyFile *keyfile, const char *prefix)
{
char **groups;
gsize i, j, ngroups;
char *connection_tag = NULL;
ConnectionInfo *connection_infos = NULL;
MatchSectionInfo *match_section_infos = NULL;
/* get the list of existing [connection.\+] sections that we consider
* for nm_config_data_get_connection_default().
/* get the list of existing [connection.\+]/[device.\+] sections.
*
* We expect the sections in their right order, with lowest priority
* first. Only exception is the (literal) [connection] section, which
* we will always reorder to the end. */
groups = g_key_file_get_groups (keyfile, &ngroups);
if (!groups)
ngroups = 0;
else if (ngroups > 0) {
return NULL;
if (ngroups > 0) {
gsize l = strlen (prefix);
for (i = 0, j = 0; i < ngroups; i++) {
if (g_str_has_prefix (groups[i], NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)) {
if (groups[i][NM_STRLEN (NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION)] == '\0')
if (g_str_has_prefix (groups[i], prefix)) {
if (groups[i][l] == '\0')
connection_tag = groups[i];
else
groups[j++] = groups[i];
@ -1135,18 +1242,23 @@ _get_connection_infos (GKeyFile *keyfile)
ngroups = j;
}
connection_infos = g_new0 (ConnectionInfo, ngroups + 1 + (connection_tag ? 1 : 0));
if (ngroups == 0 && !connection_tag) {
g_free (groups);
return NULL;
}
match_section_infos = g_new0 (MatchSectionInfo, ngroups + 1 + (connection_tag ? 1 : 0));
for (i = 0; i < ngroups; i++) {
/* pass ownership of @group on... */
_get_connection_info_init (&connection_infos[i], keyfile, groups[ngroups - i - 1]);
_get_connection_info_init (&match_section_infos[i], keyfile, groups[ngroups - i - 1]);
}
if (connection_tag) {
/* pass ownership of @connection_tag on... */
_get_connection_info_init (&connection_infos[i], keyfile, connection_tag);
_get_connection_info_init (&match_section_infos[i], keyfile, connection_tag);
}
g_free (groups);
return connection_infos;
return match_section_infos;
}
/************************************************************************/
@ -1306,7 +1418,6 @@ static void
finalize (GObject *gobject)
{
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (gobject);
guint i;
g_free (priv->config_main_file);
g_free (priv->config_description);
@ -1326,13 +1437,8 @@ finalize (GObject *gobject)
nm_global_dns_config_free (priv->global_dns);
if (priv->connection_infos) {
for (i = 0; priv->connection_infos[i].group_name; i++) {
g_free (priv->connection_infos[i].group_name);
g_slist_free_full (priv->connection_infos[i].match_device.spec, g_free);
}
g_free (priv->connection_infos);
}
_match_section_infos_free (priv->connection_infos);
_match_section_infos_free (priv->device_infos);
g_key_file_unref (priv->keyfile);
if (priv->keyfile_user)
@ -1359,7 +1465,8 @@ constructed (GObject *object)
priv->keyfile = _merge_keyfiles (priv->keyfile_user, priv->keyfile_intern);
priv->connection_infos = _get_connection_infos (priv->keyfile);
priv->connection_infos = _match_section_infos_construct (priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION);
priv->device_infos = _match_section_infos_construct (priv->keyfile, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE);
priv->connectivity.uri = nm_strstrip (g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "uri", NULL));
priv->connectivity.response = g_key_file_get_string (priv->keyfile, NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, "response", NULL);

View File

@ -183,6 +183,17 @@ char *nm_config_data_get_connection_default (const NMConfigData *self,
const char *property,
NMDevice *device);
char *nm_config_data_get_device_config (const NMConfigData *self,
const char *property,
NMDevice *device,
gboolean *has_match);
gboolean nm_config_data_get_device_config_boolean (const NMConfigData *self,
const char *property,
NMDevice *device,
gint val_no_match,
gint val_invalid);
char **nm_config_data_get_groups (const NMConfigData *self);
char **nm_config_data_get_keys (const NMConfigData *self, const char *group);
gboolean nm_config_data_is_intern_atomic_group (const NMConfigData *self, const char *group);

View File

@ -399,7 +399,9 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
priv = NM_CONFIG_GET_PRIVATE (self);
hw_address = nm_device_get_hw_address (device);
hw_address = nm_device_get_permanent_hw_address (device, FALSE);
if (!hw_address)
return;
no_auto_default_current = nm_config_data_get_no_auto_default (priv->config_data);
@ -576,14 +578,7 @@ _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
{
const char *a, *b;
gboolean a_is_connection, b_is_connection;
/* basic NULL checking... */
if (pa == pb)
return 0;
if (!pa)
return -1;
if (!pb)
return 1;
gboolean a_is_device, b_is_device;
a = *pa;
b = *pb;
@ -598,16 +593,34 @@ _sort_groups_cmp (const char **pa, const char **pb, gpointer dummy)
return 1;
return -1;
}
if (!a_is_connection) {
/* both are non-connection entries. Don't reorder. */
return 0;
if (a_is_connection) {
/* both are [connection.\+] entires. Reverse their order.
* One of the sections might be literally [connection]. That section
* is special and it's order will be fixed later. It doesn't actually
* matter here how it compares with [connection.\+] sections. */
return pa > pb ? -1 : 1;
}
/* both are [connection.\+] entires. Reverse their order.
* One of the sections might be literally [connection]. That section
* is special and it's order will be fixed later. It doesn't actually
* matter here how it compares with [connection.\+] sections. */
return pa > pb ? -1 : 1;
a_is_device = g_str_has_prefix (a, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE);
b_is_device = g_str_has_prefix (b, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE);
if (a_is_device != b_is_device) {
/* one is a [device*] entry, the other not. We sort [device*] entires
* after. */
if (a_is_device)
return 1;
return -1;
}
if (a_is_device) {
/* both are [device.\+] entires. Reverse their order.
* One of the sections might be literally [device]. That section
* is special and it's order will be fixed later. It doesn't actually
* matter here how it compares with [device.\+] sections. */
return pa > pb ? -1 : 1;
}
/* don't reorder the rest. */
return 0;
}
void
@ -630,7 +643,8 @@ _setting_is_device_spec (const char *group, const char *key)
|| _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "ignore-carrier")
|| _IS (NM_CONFIG_KEYFILE_GROUP_MAIN, "assume-ipv6ll-only")
|| _IS (NM_CONFIG_KEYFILE_GROUP_KEYFILE, "unmanaged-devices")
|| (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION) && !strcmp (key, "match-device"));
|| (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION) && !strcmp (key, "match-device"))
|| (g_str_has_prefix (group, NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE ) && !strcmp (key, "match-device"));
}
static gboolean

View File

@ -45,6 +45,7 @@
#define NM_CONFIG_KEYFILE_GROUPPREFIX_INTERN ".intern."
#define NM_CONFIG_KEYFILE_GROUPPREFIX_CONNECTION "connection"
#define NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "device"
#define NM_CONFIG_KEYFILE_GROUPPREFIX_GLOBAL_DNS_DOMAIN "global-dns-domain-"
#define NM_CONFIG_KEYFILE_GROUPPREFIX_TEST_APPEND_STRINGLIST ".test-append-stringlist"
@ -69,6 +70,8 @@
#define NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED "managed"
#define NM_CONFIG_KEYFILE_KEY_AUDIT "audit"
#define NM_CONFIG_KEYFILE_KEY_DEVICE_IGNORE_CARRIER "ignore-carrier"
#define NM_CONFIG_KEYFILE_KEYPREFIX_WAS ".was."
#define NM_CONFIG_KEYFILE_KEYPREFIX_SET ".set."

View File

@ -26,6 +26,7 @@
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <poll.h>
#include <unistd.h>
#include <stdlib.h>
#include <resolv.h>
@ -54,7 +55,7 @@
#endif
G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int));
int _nm_utils_testing = 0;
static int _nm_utils_testing = 0;
gboolean
nm_utils_get_testing_initialized ()
@ -1271,8 +1272,10 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
guint hwaddr_len = 0;
guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX];
g_return_val_if_fail (hwaddr != NULL, NM_MATCH_SPEC_NO_MATCH);
nm_assert (nm_utils_hwaddr_valid (hwaddr, -1));
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
@ -1293,7 +1296,15 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
else if (except)
continue;
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr, -1)) {
if (G_UNLIKELY (hwaddr_len == 0)) {
hwaddr_len = _nm_utils_hwaddr_length (hwaddr);
if (!hwaddr_len)
g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH);
if (!nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, hwaddr_len))
nm_assert_not_reached ();
}
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len)) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
@ -2701,6 +2712,123 @@ nm_utils_machine_id_read (void)
/*****************************************************************************/
/* taken from systemd's fd_wait_for_event(). Note that the timeout
* is here in nano-seconds, not micro-seconds. */
int
nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns)
{
struct pollfd pollfd = {
.fd = fd,
.events = event,
};
struct timespec ts, *pts;
int r;
if (timeout_ns < 0)
pts = NULL;
else {
ts.tv_sec = (time_t) (timeout_ns / NM_UTILS_NS_PER_SECOND);
ts.tv_nsec = (long int) (timeout_ns % NM_UTILS_NS_PER_SECOND);
pts = &ts;
}
r = ppoll (&pollfd, 1, pts, NULL);
if (r < 0)
return -errno;
if (r == 0)
return 0;
return pollfd.revents;
}
/* taken from systemd's loop_read() */
ssize_t
nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll)
{
uint8_t *p = buf;
ssize_t n = 0;
g_return_val_if_fail (fd >= 0, -EINVAL);
g_return_val_if_fail (buf, -EINVAL);
/* If called with nbytes == 0, let's call read() at least
* once, to validate the operation */
if (nbytes > (size_t) SSIZE_MAX)
return -EINVAL;
do {
ssize_t k;
k = read (fd, p, nbytes);
if (k < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN && do_poll) {
/* We knowingly ignore any return value here,
* and expect that any error/EOF is reported
* via read() */
(void) nm_utils_fd_wait_for_event (fd, POLLIN, -1);
continue;
}
return n > 0 ? n : -errno;
}
if (k == 0)
return n;
g_assert ((size_t) k <= nbytes);
p += k;
nbytes -= k;
n += k;
} while (nbytes > 0);
return n;
}
/* taken from systemd's loop_read_exact() */
int
nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll)
{
ssize_t n;
n = nm_utils_fd_read_loop (fd, buf, nbytes, do_poll);
if (n < 0)
return (int) n;
if ((size_t) n != nbytes)
return -EIO;
return 0;
}
/* taken from systemd's dev_urandom(). */
int
nm_utils_read_urandom (void *p, size_t nbytes)
{
int fd = -1;
int r;
again:
fd = open ("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0) {
r = errno;
if (r == EINTR)
goto again;
return r == ENOENT ? -ENOSYS : -r;
}
r = nm_utils_fd_read_loop_exact (fd, p, nbytes, TRUE);
close (fd);
return r;
}
/*****************************************************************************/
guint8 *
nm_utils_secret_key_read (gsize *out_key_len, GError **error)
{
@ -2719,34 +2847,28 @@ nm_utils_secret_key_read (gsize *out_key_len, GError **error)
key_len = 0;
}
} else {
int urandom = open ("/dev/urandom", O_RDONLY);
int r;
mode_t key_mask;
if (urandom == -1) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
"Can't open /dev/urandom: %s", strerror (errno));
key_len = 0;
goto out;
}
/* RFC7217 mandates the key SHOULD be at least 128 bits.
* Let's use twice as much. */
key_len = 32;
secret_key = g_malloc (key_len);
r = nm_utils_read_urandom (secret_key, key_len);
if (r < 0) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
"Can't read /dev/urandom: %s", strerror (-r));
key_len = 0;
goto out;
}
key_mask = umask (0077);
if (read (urandom, secret_key, key_len) == key_len) {
if (!g_file_set_contents (NMSTATEDIR "/secret_key", (char *) secret_key, key_len, error)) {
g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key: ");
key_len = 0;
}
} else {
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
"Could not obtain a secret");
if (!g_file_set_contents (NMSTATEDIR "/secret_key", (char *) secret_key, key_len, error)) {
g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key: ");
key_len = 0;
}
umask (key_mask);
close (urandom);
}
out:
@ -2953,9 +3075,10 @@ nm_utils_inet6_interface_identifier_to_token (NMUtilsIPv6IfaceId iid, char *buf)
/*****************************************************************************/
static gboolean
_set_stable_privacy (struct in6_addr *addr,
_set_stable_privacy (guint8 stable_type,
struct in6_addr *addr,
const char *ifname,
const char *uuid,
const char *network_id,
guint dad_counter,
guint8 *secret_key,
gsize key_len,
@ -2979,11 +3102,24 @@ _set_stable_privacy (struct in6_addr *addr,
key_len = MIN (key_len, G_MAXUINT32);
if (stable_type != NM_UTILS_STABLE_TYPE_UUID) {
/* Preferably, we would always like to include the stable-type,
* but for backward compatibility reasons, we cannot for UUID.
*
* That is no real problem and it is still impossible to
* force a collision here, because of how the remaining
* fields are hashed. That is, as we also hash @key_len
* and the terminating '\0' of @network_id, it is unambigiously
* possible to revert the process and deduce the @stable_type.
*/
g_checksum_update (sum, &stable_type, sizeof (stable_type));
}
g_checksum_update (sum, addr->s6_addr, 8);
g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
if (!uuid)
uuid = "";
g_checksum_update (sum, (const guchar *) uuid, strlen (uuid) + 1);
if (!network_id)
network_id = "";
g_checksum_update (sum, (const guchar *) network_id, strlen (network_id) + 1);
tmp[0] = htonl (dad_counter);
tmp[1] = htonl (key_len);
g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
@ -3009,15 +3145,20 @@ _set_stable_privacy (struct in6_addr *addr,
* Returns: %TRUE on success, %FALSE if the address could not be generated.
*/
gboolean
nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
nm_utils_ipv6_addr_set_stable_privacy (NMUtilsStableType stable_type,
struct in6_addr *addr,
const char *ifname,
const char *uuid,
const char *network_id,
guint dad_counter,
GError **error)
{
gs_free guint8 *secret_key = NULL;
gsize key_len = 0;
nm_assert (NM_IN_SET (stable_type,
NM_UTILS_STABLE_TYPE_UUID,
NM_UTILS_STABLE_TYPE_STABLE_ID));
if (dad_counter >= RFC7217_IDGEN_RETRIES) {
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
"Too many DAD collisions");
@ -3028,10 +3169,151 @@ nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
if (!secret_key)
return FALSE;
return _set_stable_privacy (addr, ifname, uuid, dad_counter,
return _set_stable_privacy (stable_type, addr, ifname, network_id, dad_counter,
secret_key, key_len, error);
}
/*****************************************************************************/
static void
_hw_addr_eth_complete (struct ether_addr *addr,
const char *current_mac_address,
const char *generate_mac_address_mask)
{
struct ether_addr mask;
struct ether_addr oui;
struct ether_addr *ouis;
gsize ouis_len;
guint i;
/* the second LSB of the first octet means
* "globally unique, OUI enforced, BIA (burned-in-address)"
* vs. "locally-administered". By default, set it to
* generate locally-administered addresses.
*
* Maybe be overwritten by a mask below. */
addr->ether_addr_octet[0] |= 2;
if (!generate_mac_address_mask || !*generate_mac_address_mask)
goto out;
if (!_nm_utils_generate_mac_address_mask_parse (generate_mac_address_mask,
&mask,
&ouis,
&ouis_len,
NULL))
goto out;
nm_assert ((ouis == NULL) ^ (ouis_len != 0));
if (ouis) {
/* g_random_int() is good enough here. It uses a static GRand instance
* that is seeded from /dev/urandom. */
oui = ouis[g_random_int () % ouis_len];
g_free (ouis);
} else {
if (!nm_utils_hwaddr_aton (current_mac_address, &oui, ETH_ALEN))
goto out;
}
for (i = 0; i < ETH_ALEN; i++) {
const guint8 a = addr->ether_addr_octet[i];
const guint8 o = oui.ether_addr_octet[i];
const guint8 m = mask.ether_addr_octet[i];
addr->ether_addr_octet[i] = (a & ~m) | (o & m);
}
out:
/* The LSB of the first octet must always be cleared,
* it means Unicast vs. Multicast */
addr->ether_addr_octet[0] &= ~1;
}
char *
nm_utils_hw_addr_gen_random_eth (const char *current_mac_address,
const char *generate_mac_address_mask)
{
struct ether_addr bin_addr;
if (nm_utils_read_urandom (&bin_addr, ETH_ALEN) < 0)
return NULL;
_hw_addr_eth_complete (&bin_addr, current_mac_address, generate_mac_address_mask);
return nm_utils_hwaddr_ntoa (&bin_addr, ETH_ALEN);
}
static char *
_hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
const char *stable_id,
const guint8 *secret_key,
gsize key_len,
const char *ifname,
const char *current_mac_address,
const char *generate_mac_address_mask)
{
GChecksum *sum;
guint32 tmp;
guint8 digest[32];
gsize len = sizeof (digest);
struct ether_addr bin_addr;
guint8 stable_type_uint8;
nm_assert (stable_id);
nm_assert (NM_IN_SET (stable_type,
NM_UTILS_STABLE_TYPE_UUID,
NM_UTILS_STABLE_TYPE_STABLE_ID));
nm_assert (secret_key);
sum = g_checksum_new (G_CHECKSUM_SHA256);
if (!sum)
return NULL;
key_len = MIN (key_len, G_MAXUINT32);
stable_type_uint8 = stable_type;
g_checksum_update (sum, (const guchar *) &stable_type_uint8, sizeof (stable_type_uint8));
tmp = htonl ((guint32) key_len);
g_checksum_update (sum, (const guchar *) &tmp, sizeof (tmp));
g_checksum_update (sum, (const guchar *) secret_key, key_len);
g_checksum_update (sum, (const guchar *) (ifname ?: ""), ifname ? (strlen (ifname) + 1) : 1);
g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
g_checksum_get_digest (sum, digest, &len);
g_checksum_free (sum);
g_return_val_if_fail (len == 32, NULL);
memcpy (&bin_addr, digest, ETH_ALEN);
_hw_addr_eth_complete (&bin_addr, current_mac_address, generate_mac_address_mask);
return nm_utils_hwaddr_ntoa (&bin_addr, ETH_ALEN);
}
char *
nm_utils_hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
const char *stable_id,
const char *ifname,
const char *current_mac_address,
const char *generate_mac_address_mask)
{
gs_free guint8 *secret_key = NULL;
gsize key_len = 0;
g_return_val_if_fail (stable_id, NULL);
secret_key = nm_utils_secret_key_read (&key_len, NULL);
if (!secret_key)
return NULL;
return _hw_addr_gen_stable_eth (stable_type,
stable_id,
secret_key,
key_len,
ifname,
current_mac_address,
generate_mac_address_mask);
}
/*****************************************************************************/
/**
* nm_utils_setpgid:
* @unused: unused

View File

@ -310,6 +310,12 @@ const char *nm_utils_ip4_property_path (const char *ifname, const char *property
gboolean nm_utils_is_specific_hostname (const char *name);
int nm_utils_fd_wait_for_event (int fd, int event, gint64 timeout_ns);
ssize_t nm_utils_fd_read_loop (int fd, void *buf, size_t nbytes, bool do_poll);
int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll);
int nm_utils_read_urandom (void *p, size_t n);
char *nm_utils_machine_id_read (void);
gboolean nm_utils_machine_id_parse (const char *id_str, /*uuid_t*/ guchar *out_uuid);
@ -353,12 +359,26 @@ gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
guint dev_id,
NMUtilsIPv6IfaceId *out_iid);
gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
typedef enum {
NM_UTILS_STABLE_TYPE_UUID = 0,
NM_UTILS_STABLE_TYPE_STABLE_ID = 1,
} NMUtilsStableType;
gboolean nm_utils_ipv6_addr_set_stable_privacy (NMUtilsStableType id_type,
struct in6_addr *addr,
const char *ifname,
const char *uuid,
const char *network_id,
guint dad_counter,
GError **error);
char *nm_utils_hw_addr_gen_random_eth (const char *current_mac_address,
const char *generate_mac_address_mask);
char *nm_utils_hw_addr_gen_stable_eth (NMUtilsStableType stable_type,
const char *stable_id,
const char *ifname,
const char *current_mac_address,
const char *generate_mac_address_mask);
void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
void nm_utils_setpgid (gpointer unused);

View File

@ -66,6 +66,7 @@ static struct {
int tempaddr;
char *ifname;
char *uuid;
char *stable_id;
char *dhcp4_address;
char *dhcp4_clientid;
char *dhcp4_hostname;
@ -278,8 +279,9 @@ do_early_setup (int *argc, char **argv[])
gint64 priority64_v6 = -1;
GOptionEntry options[] = {
/* Interface/IP config */
{ "ifname", 'i', 0, G_OPTION_ARG_STRING, &global_opt.ifname, N_("The interface to manage"), N_("eth0") },
{ "uuid", 'u', 0, G_OPTION_ARG_STRING, &global_opt.uuid, N_("Connection UUID"), N_("661e8cd0-b618-46b8-9dc9-31a52baaa16b") },
{ "ifname", 'i', 0, G_OPTION_ARG_STRING, &global_opt.ifname, N_("The interface to manage"), "eth0" },
{ "uuid", 'u', 0, G_OPTION_ARG_STRING, &global_opt.uuid, N_("Connection UUID"), "661e8cd0-b618-46b8-9dc9-31a52baaa16b" },
{ "stable-id", '\0', 0, G_OPTION_ARG_STRING, &global_opt.stable_id, N_("Connection Token for Stable IDs"), "eth" },
{ "slaac", 's', 0, G_OPTION_ARG_NONE, &global_opt.slaac, N_("Whether to manage IPv6 SLAAC"), NULL },
{ "slaac-required", '6', 0, G_OPTION_ARG_NONE, &global_opt.slaac_required, N_("Whether SLAAC must be successful"), NULL },
{ "slaac-tempaddr", 't', 0, G_OPTION_ARG_INT, &global_opt.tempaddr, N_("Use an IPv6 temporary privacy address"), NULL },
@ -469,9 +471,23 @@ main (int argc, char *argv[])
}
if (global_opt.slaac) {
NMUtilsStableType stable_type = NM_UTILS_STABLE_TYPE_UUID;
const char *stable_id = global_opt.uuid;
nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, TRUE);
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL);
if ( global_opt.stable_id
&& (global_opt.stable_id[0] >= '0' && global_opt.stable_id[0] <= '9')
&& global_opt.stable_id[1] == ' ') {
/* strict parsing of --stable-id, which is the numeric stable-type
* and the ID, joined with one space. For now, only support stable-types
* from 0 to 9. */
stable_type = (global_opt.stable_id[0] - '0');
stable_id = &global_opt.stable_id[2];
}
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname,
stable_type, stable_id,
global_opt.addr_gen_mode, NULL);
g_assert (rdisc);
if (iid)

View File

@ -595,7 +595,7 @@ nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex)
}
static NMDevice *
find_device_by_hw_addr (NMManager *manager, const char *hwaddr)
find_device_by_permanent_hw_addr (NMManager *manager, const char *hwaddr)
{
GSList *iter;
const char *device_addr;
@ -604,7 +604,7 @@ find_device_by_hw_addr (NMManager *manager, const char *hwaddr)
if (nm_utils_hwaddr_valid (hwaddr, -1)) {
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
device_addr = nm_device_get_hw_address (NM_DEVICE (iter->data));
device_addr = nm_device_get_permanent_hw_address (NM_DEVICE (iter->data), FALSE);
if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1))
return NM_DEVICE (iter->data);
}
@ -945,28 +945,12 @@ remove_device (NMManager *self,
nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE));
if (allow_unmanage && nm_device_get_managed (device, FALSE)) {
unmanage = TRUE;
if (!quitting) {
if (quitting)
unmanage = nm_device_unmanage_on_quit (device);
else {
/* the device is already gone. Unmanage it. */
} else {
/* Leave certain devices alone when quitting so their configuration
* can be taken over when NM restarts. This ensures connectivity while
* NM is stopped.
*/
if (nm_device_uses_assumed_connection (device)) {
/* An assume connection must be left alone */
unmanage = FALSE;
} else if (!nm_device_get_act_request (device)) {
/* a device without any active connection is either UNAVAILABLE or DISCONNECTED
* state. Since we don't know whether the device was upped by NetworkManager,
* we must leave it up on exit. */
unmanage = FALSE;
} else if (!nm_platform_link_can_assume (NM_PLATFORM_GET, nm_device_get_ifindex (device))) {
/* The device has no layer 3 configuration. Leave it up. */
unmanage = FALSE;
} else if (nm_device_can_assume_active_connection (device))
unmanage = FALSE;
unmanage = TRUE;
}
if (unmanage) {
@ -1054,7 +1038,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection, NM
return parent;
/* Maybe a hardware address */
parent = find_device_by_hw_addr (self, parent_name);
parent = find_device_by_permanent_hw_addr (self, parent_name);
if (parent)
return parent;

View File

@ -321,7 +321,8 @@ NMRDisc *
nm_lndp_rdisc_new (NMPlatform *platform,
int ifindex,
const char *ifname,
const char *uuid,
NMUtilsStableType stable_type,
const char *network_id,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
GError **error)
{
@ -342,7 +343,8 @@ nm_lndp_rdisc_new (NMPlatform *platform,
rdisc->ifindex = ifindex;
rdisc->ifname = g_strdup (ifname);
rdisc->uuid = g_strdup (uuid);
rdisc->stable_type = stable_type;
rdisc->network_id = g_strdup (network_id);
rdisc->addr_gen_mode = addr_gen_mode;
rdisc->max_addresses = ipv6_sysctl_get (platform, ifname, "max_addresses",

View File

@ -22,6 +22,7 @@
#define __NETWORKMANAGER_LNDP_RDISC_H__
#include "nm-rdisc.h"
#include "nm-core-utils.h"
#define NM_TYPE_LNDP_RDISC (nm_lndp_rdisc_get_type ())
#define NM_LNDP_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LNDP_RDISC, NMLNDPRDisc))
@ -47,7 +48,8 @@ GType nm_lndp_rdisc_get_type (void);
NMRDisc *nm_lndp_rdisc_new (NMPlatform *platform,
int ifindex,
const char *ifname,
const char *uuid,
NMUtilsStableType stable_type,
const char *network_id,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
GError **error);

View File

@ -140,9 +140,10 @@ complete_address (NMRDisc *rdisc, NMRDiscAddress *addr)
GError *error = NULL;
if (rdisc->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
if (!nm_utils_ipv6_addr_set_stable_privacy (&addr->address,
if (!nm_utils_ipv6_addr_set_stable_privacy (rdisc->stable_type,
&addr->address,
rdisc->ifname,
rdisc->uuid,
rdisc->network_id,
addr->dad_counter++,
&error)) {
_LOGW ("complete-address: failed to generate an stable-privacy address: %s",
@ -777,7 +778,7 @@ finalize (GObject *object)
NMRDisc *rdisc = NM_RDISC (object);
g_free (rdisc->ifname);
g_free (rdisc->uuid);
g_free (rdisc->network_id);
g_array_unref (rdisc->gateways);
g_array_unref (rdisc->addresses);
g_array_unref (rdisc->routes);

View File

@ -116,9 +116,11 @@ typedef struct {
NMPlatform *_platform;
NMPNetns *_netns;
NMUtilsStableType stable_type;
int ifindex;
char *ifname;
char *uuid;
char *network_id;
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
NMUtilsIPv6IfaceId iid;
gint32 max_addresses;

View File

@ -64,6 +64,7 @@ main (int argc, char **argv)
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
ifindex,
ifname,
NM_UTILS_STABLE_TYPE_UUID,
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
&error);

View File

@ -1879,11 +1879,11 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
NMSettingConnection *s_con;
NMSettingWired *s_wired;
const char *setting_hwaddr;
const char *device_hwaddr;
const char *perm_hw_addr;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
device_hwaddr = nm_device_get_hw_address (device);
perm_hw_addr = nm_device_get_permanent_hw_address (device, FALSE);
/* Find a wired connection locked to the given MAC address, if any */
g_hash_table_iter_init (&iter, priv->connections);
@ -1917,8 +1917,8 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
setting_hwaddr = nm_setting_wired_get_mac_address (s_wired);
if (setting_hwaddr) {
/* A connection mac-locked to this device */
if ( device_hwaddr
&& nm_utils_hwaddr_matches (setting_hwaddr, -1, device_hwaddr, -1))
if ( perm_hw_addr
&& nm_utils_hwaddr_matches (setting_hwaddr, -1, perm_hw_addr, -1))
return TRUE;
} else {
/* A connection that applies to any wired device */

View File

@ -128,6 +128,7 @@ make_connection_setting (const char *file,
NMSettingConnectionLldp lldp;
const char *ifcfg_name = NULL;
char *new_id, *uuid = NULL, *zone = NULL, *value;
gs_free char *stable_id = NULL;
ifcfg_name = utils_get_ifcfg_name (file, TRUE);
if (!ifcfg_name)
@ -146,9 +147,12 @@ make_connection_setting (const char *file,
uuid = nm_utils_uuid_generate_from_string (ifcfg->fileName, -1, NM_UTILS_UUID_TYPE_LEGACY, NULL);
}
stable_id = svGetValue (ifcfg, "STABLE_ID", FALSE);
g_object_set (s_con,
NM_SETTING_CONNECTION_TYPE, type,
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_STABLE_ID, stable_id,
NULL);
g_free (uuid);
@ -3364,6 +3368,10 @@ make_wireless_setting (shvarFile *ifcfg,
g_free (value);
}
value = svGetValue (ifcfg, "GENERATE_MAC_ADDRESS_MASK", FALSE);
g_object_set (s_wireless, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, value, NULL);
g_free (value);
value = svGetValue (ifcfg, "HWADDR_BLACKLIST", FALSE);
if (value) {
char **strv;
@ -3878,6 +3886,10 @@ make_wired_setting (shvarFile *ifcfg,
g_free (value);
}
value = svGetValue (ifcfg, "GENERATE_MAC_ADDRESS_MASK", FALSE);
g_object_set (s_wired, NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, value, NULL);
g_free (value);
value = svGetValue (ifcfg, "HWADDR_BLACKLIST", FALSE);
if (value) {
char **strv;

View File

@ -853,6 +853,10 @@ write_wireless_setting (NMConnection *connection,
cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
svSetValue (ifcfg, "GENERATE_MAC_ADDRESS_MASK",
nm_setting_wireless_get_generate_mac_address_mask (s_wireless),
FALSE);
svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
if (macaddr_blacklist[0]) {
@ -1111,6 +1115,10 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
svSetValue (ifcfg, "GENERATE_MAC_ADDRESS_MASK",
nm_setting_wired_get_generate_mac_address_mask (s_wired),
FALSE);
svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
if (macaddr_blacklist[0]) {
@ -1255,19 +1263,22 @@ write_wired_for_virtual (NMConnection *connection, shvarFile *ifcfg)
has_wired = TRUE;
device_mac = nm_setting_wired_get_mac_address (s_wired);
if (device_mac)
svSetValue (ifcfg, "HWADDR", device_mac, FALSE);
svSetValue (ifcfg, "HWADDR", device_mac, FALSE);
cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
if (cloned_mac)
svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
svSetValue (ifcfg, "MACADDR", cloned_mac, FALSE);
svSetValue (ifcfg, "GENERATE_MAC_ADDRESS_MASK",
nm_setting_wired_get_generate_mac_address_mask (s_wired),
FALSE);
mtu = nm_setting_wired_get_mtu (s_wired);
if (mtu) {
tmp = g_strdup_printf ("%u", mtu);
svSetValue (ifcfg, "MTU", tmp, FALSE);
g_free (tmp);
}
} else
svSetValue (ifcfg, "MTU", NULL, FALSE);
}
return has_wired;
}
@ -1800,6 +1811,7 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
svSetValue (ifcfg, "STABLE_ID", nm_setting_connection_get_stable_id (s_con), FALSE);
svSetValue (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con), FALSE);
svSetValue (ifcfg, "ONBOOT",
nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",

View File

@ -47,7 +47,6 @@ typedef struct
GHashTable *config;
GHashTable *blobs;
guint32 ap_scan;
NMSettingMacRandomization mac_randomization;
gboolean fast_required;
gboolean dispose_has_run;
} NMSupplicantConfigPrivate;
@ -85,7 +84,6 @@ nm_supplicant_config_init (NMSupplicantConfig * self)
(GDestroyNotify) blob_free);
priv->ap_scan = 1;
priv->mac_randomization = NM_SETTING_MAC_RANDOMIZATION_DEFAULT;
priv->dispose_has_run = FALSE;
}
@ -272,32 +270,6 @@ nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self)
return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan;
}
const char *
nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self)
{
g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), 0);
/**
* mac_addr - MAC address policy default
*
* 0 = use permanent MAC address
* 1 = use random MAC address for each ESS connection
* 2 = like 1, but maintain OUI (with local admin bit set)
*
* By default, permanent MAC address is used unless policy is changed by
* the per-network mac_addr parameter.
*/
switch (NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->mac_randomization) {
case NM_SETTING_MAC_RANDOMIZATION_ALWAYS:
return "1";
case NM_SETTING_MAC_RANDOMIZATION_NEVER:
case NM_SETTING_MAC_RANDOMIZATION_DEFAULT:
default:
return "0";
}
}
gboolean
nm_supplicant_config_fast_required (NMSupplicantConfig *self)
{
@ -385,8 +357,6 @@ gboolean
nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
NMSettingWireless * setting,
guint32 fixed_freq,
NMSupplicantFeature mac_randomization_support,
NMSettingMacRandomization mac_randomization_fallback,
GError **error)
{
NMSupplicantConfigPrivate *priv;
@ -477,23 +447,6 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
}
}
priv->mac_randomization = nm_setting_wireless_get_mac_address_randomization (setting);
if (priv->mac_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) {
priv->mac_randomization = mac_randomization_fallback;
if (priv->mac_randomization == NM_SETTING_MAC_RANDOMIZATION_DEFAULT) {
/* Don't use randomization, unless explicitly enabled.
* Randomization can work badly with captive portals. */
priv->mac_randomization = NM_SETTING_MAC_RANDOMIZATION_NEVER;
}
}
if ( priv->mac_randomization != NM_SETTING_MAC_RANDOMIZATION_NEVER
&& mac_randomization_support != NM_SUPPLICANT_FEATURE_YES) {
g_set_error (error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
"cannot enable mac-randomization due to missing supplicant support");
return FALSE;
}
return TRUE;
}

View File

@ -54,8 +54,6 @@ NMSupplicantConfig *nm_supplicant_config_new (void);
guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
const char *nm_supplicant_config_get_mac_randomization (NMSupplicantConfig *self);
gboolean nm_supplicant_config_fast_required (NMSupplicantConfig *self);
GVariant *nm_supplicant_config_to_variant (NMSupplicantConfig *self);
@ -65,8 +63,6 @@ GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self);
gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self,
NMSettingWireless *setting,
guint32 fixed_freq,
NMSupplicantFeature mac_randomization_support,
NMSettingMacRandomization mac_randomization_fallback,
GError **error);
gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,

View File

@ -503,12 +503,6 @@ nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
priv->ap_support = ap_support;
}
NMSupplicantFeature
nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self)
{
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->mac_randomization_support;
}
static void
set_preassoc_scan_mac_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
{
@ -563,7 +557,7 @@ iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data
g_variant_new ("(ssv)",
WPAS_DBUS_IFACE_INTERFACE,
"PreassocMacAddr",
g_variant_new_string ("1")),
g_variant_new_string ("0")),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->init_cancellable,
@ -1223,9 +1217,7 @@ set_mac_randomization_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user
return;
}
_LOGI ("config: set MAC randomization to %s",
nm_supplicant_config_get_mac_randomization (priv->cfg));
_LOGT ("config: set MAC randomization to 0");
add_network (self);
}
@ -1256,23 +1248,20 @@ set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
nm_supplicant_config_get_ap_scan (priv->cfg));
if (priv->mac_randomization_support == NM_SUPPLICANT_FEATURE_YES) {
const char *mac_randomization = nm_supplicant_config_get_mac_randomization (priv->cfg);
/* Enable/disable association MAC address randomization */
g_dbus_proxy_call (priv->iface_proxy,
DBUS_INTERFACE_PROPERTIES ".Set",
g_variant_new ("(ssv)",
WPAS_DBUS_IFACE_INTERFACE,
"MacAddr",
g_variant_new_string (mac_randomization)),
g_variant_new_string ("0")),
G_DBUS_CALL_FLAGS_NONE,
-1,
priv->assoc_cancellable,
(GAsyncReadyCallback) set_mac_randomization_cb,
self);
} else {
} else
add_network (self);
}
}
gboolean

View File

@ -165,6 +165,4 @@ NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterfac
void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
NMSupplicantFeature apmode);
NMSupplicantFeature nm_supplicant_interface_get_mac_randomization_support (NMSupplicantInterface *self);
#endif /* NM_SUPPLICANT_INTERFACE_H */

View File

@ -160,8 +160,6 @@ test_wifi_open (void)
g_assert (nm_supplicant_config_add_setting_wireless (config,
s_wifi,
0,
NM_SUPPLICANT_FEATURE_UNKNOWN,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();
@ -265,8 +263,6 @@ test_wifi_wep_key (const char *detail,
g_assert (nm_supplicant_config_add_setting_wireless (config,
s_wifi,
0,
NM_SUPPLICANT_FEATURE_UNKNOWN,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();
@ -410,8 +406,6 @@ test_wifi_wpa_psk (const char *detail,
g_assert (nm_supplicant_config_add_setting_wireless (config,
s_wifi,
0,
NM_SUPPLICANT_FEATURE_UNKNOWN,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();
@ -557,8 +551,6 @@ test_wifi_eap (void)
g_assert (nm_supplicant_config_add_setting_wireless (config,
s_wifi,
0,
NM_SUPPLICANT_FEATURE_UNKNOWN,
NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
&error));
g_assert_no_error (error);
g_test_assert_expected_messages ();

View File

@ -38,17 +38,6 @@ nm_test_device_init (NMTestDevice *self)
/* We jump over NMDevice's construct/destruct methods, which require NMPlatform
* and NMConnectionProvider to be initialized.
*/
static GObject*
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
return PARENT_CLASS->constructor (type,
n_construct_params,
construct_params);
}
static void
constructed (GObject *object)
{
@ -73,7 +62,6 @@ nm_test_device_class_init (NMTestDeviceClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
object_class->constructor = constructor;
object_class->constructed = constructed;
object_class->dispose = dispose;
@ -85,6 +73,6 @@ nm_test_device_new (const char *hwaddr)
{
return g_object_new (NM_TYPE_TEST_DEVICE,
NM_DEVICE_IFACE, "dummy",
NM_DEVICE_HW_ADDRESS, hwaddr,
NM_DEVICE_PERM_HW_ADDRESS, hwaddr,
NULL);
}

View File

@ -34,21 +34,93 @@ test_stable_privacy (void)
struct in6_addr addr1;
inet_pton (AF_INET6, "1234::", &addr1);
_set_stable_privacy (&addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, (guint8 *) "key", 3, NULL);
_set_stable_privacy (NM_UTILS_STABLE_TYPE_UUID, &addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, (guint8 *) "key", 3, NULL);
nmtst_assert_ip6_address (&addr1, "1234::4ceb:14cd:3d54:793f");
/* We get an address without the UUID. */
inet_pton (AF_INET6, "1::", &addr1);
_set_stable_privacy (&addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
_set_stable_privacy (NM_UTILS_STABLE_TYPE_UUID, &addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
nmtst_assert_ip6_address (&addr1, "1::11aa:2530:9144:dafa");
/* We get a different address in a different network. */
inet_pton (AF_INET6, "2::", &addr1);
_set_stable_privacy (&addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
_set_stable_privacy (NM_UTILS_STABLE_TYPE_UUID, &addr1, "eth666", NULL, 384, (guint8 *) "key", 3, NULL);
nmtst_assert_ip6_address (&addr1, "2::338e:8d:c11:8726");
inet_pton (AF_INET6, "1234::", &addr1);
_set_stable_privacy (NM_UTILS_STABLE_TYPE_STABLE_ID, &addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, (guint8 *) "key", 3, NULL);
nmtst_assert_ip6_address (&addr1, "1234::ad4c:ae44:3d30:af1e");
inet_pton (AF_INET6, "1234::", &addr1);
_set_stable_privacy (NM_UTILS_STABLE_TYPE_STABLE_ID, &addr1, "eth666", "stable-id-1", 0, (guint8 *) "key", 3, NULL);
nmtst_assert_ip6_address (&addr1, "1234::4944:67b0:7a6c:1cf");
}
/*******************************************/
/*****************************************************************************/
static void
_do_test_hw_addr (NMUtilsStableType stable_type,
const char *stable_id,
const guint8 *secret_key,
gsize key_len,
const char *ifname,
const char *current_mac_address,
const char *generate_mac_address_mask,
const char **expected)
{
gs_free char *generated = NULL;
const char **e;
gboolean found = FALSE;
for (e = expected; *e; e++) {
g_assert (*e);
g_assert (nm_utils_hwaddr_valid (*e, ETH_ALEN));
}
generated = _hw_addr_gen_stable_eth (stable_type,
stable_id,
secret_key,
key_len,
ifname,
current_mac_address,
generate_mac_address_mask);
g_assert (generated);
g_assert (nm_utils_hwaddr_valid (generated, ETH_ALEN));
for (e = expected; *e; e++) {
if (!nm_utils_hwaddr_matches (generated, -1, *e, -1))
continue;
g_assert (!found);
found = TRUE;
g_assert_cmpstr (generated, ==, *e);
}
g_assert (found);
}
#define do_test_hw_addr(stable_type, stable_id, secret_key, ifname, current_mac_address, generate_mac_address_mask, ...) \
_do_test_hw_addr ((stable_type), (stable_id), (const guint8 *) ""secret_key"", NM_STRLEN (secret_key), (ifname), ""current_mac_address"", generate_mac_address_mask, (const char *[]) { __VA_ARGS__, NULL })
static void
test_hw_addr_gen_stable_eth (void)
{
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", NULL, "06:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_STABLE_ID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", NULL, "C6:AE:A9:9A:76:09");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "FF:FF:FF:00:00:00", "00:23:45:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "03:23:45:67:89:ab", "FF:FF:FF:00:00:00", "02:23:45:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "00:00:00:00:00:00", "06:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "02:00:00:00:00:00", "04:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "02:00:00:00:00:00", "04:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "02:00:00:00:00:00 00:00:00:00:00:00", "04:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "02:00:00:00:00:00 02:00:00:00:00:00", "06:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "00:00:00:00:00:00 E9:60:CE:F5:ED:2F", "06:0D:CD:0C:9E:2C");
do_test_hw_addr (NM_UTILS_STABLE_TYPE_UUID, "stable-1", "key1", "eth0", "01:23:45:67:89:ab", "02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00", "06:0D:CD:0C:9E:2C", "04:0D:CD:0C:9E:2C");
}
/*****************************************************************************/
NMTST_DEFINE ();
@ -58,6 +130,7 @@ main (int argc, char **argv)
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
g_test_add_func ("/utils/stable_privacy", test_stable_privacy);
g_test_add_func ("/utils/hw_addr_gen_stable_eth", test_hw_addr_gen_stable_eth);
return g_test_run ();
}