diff options
Diffstat (limited to 'libnm-core/nm-setting-wireless.c')
| -rw-r--r-- | libnm-core/nm-setting-wireless.c | 220 |
1 files changed, 202 insertions, 18 deletions
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c index ee4ac6f2..a7f58fe5 100644 --- a/libnm-core/nm-setting-wireless.c +++ b/libnm-core/nm-setting-wireless.c @@ -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, @@ -420,6 +424,22 @@ nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting) } /** + * 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, @@ -741,7 +762,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->mode && !_nm_utils_string_in_list (priv->mode, valid_modes)) { + if (priv->mode && !g_strv_contains (valid_modes, priv->mode)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -751,7 +772,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } - if (priv->band && !_nm_utils_string_in_list (priv->band, valid_bands)) { + if (priv->band && !g_strv_contains (valid_bands, priv->band)) { g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, @@ -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" 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); } |