summary refs log tree commit diff
path: root/libnm-core/nm-setting-wireless.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-setting-wireless.c')
-rw-r--r--libnm-core/nm-setting-wireless.c1335
1 files changed, 1335 insertions, 0 deletions
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
new file mode 100644
index 00000000..f8d22c2d
--- /dev/null
+++ b/libnm-core/nm-setting-wireless.c
@@ -0,0 +1,1335 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-wireless.h"
+#include "nm-dbus-interface.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-wireless
+ * @short_description: Describes connection properties for 802.11 Wi-Fi networks
+ *
+ * The #NMSettingWireless object is a #NMSetting subclass that describes properties
+ * necessary for connection to 802.11 Wi-Fi networks.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING,
+                         _nm_register_setting (WIRELESS, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS)
+
+#define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate))
+
+typedef struct {
+	GBytes *ssid;
+	char *mode;
+	char *band;
+	guint32 channel;
+	char *bssid;
+	guint32 rate;
+	guint32 tx_power;
+	char *device_mac_address;
+	char *cloned_mac_address;
+	GArray *mac_address_blacklist;
+	guint32 mtu;
+	GSList *seen_bssids;
+	gboolean hidden;
+} NMSettingWirelessPrivate;
+
+enum {
+	PROP_0,
+	PROP_SSID,
+	PROP_MODE,
+	PROP_BAND,
+	PROP_CHANNEL,
+	PROP_BSSID,
+	PROP_RATE,
+	PROP_TX_POWER,
+	PROP_MAC_ADDRESS,
+	PROP_CLONED_MAC_ADDRESS,
+	PROP_MAC_ADDRESS_BLACKLIST,
+	PROP_MTU,
+	PROP_SEEN_BSSIDS,
+	PROP_HIDDEN,
+
+	LAST_PROP
+};
+
+static gboolean
+match_cipher (const char *cipher,
+              const char *expected,
+              guint32 wpa_flags,
+              guint32 rsn_flags,
+              guint32 flag)
+{
+	if (strcmp (cipher, expected) != 0)
+		return FALSE;
+
+	if (!(wpa_flags & flag) && !(rsn_flags & flag))
+		return FALSE;
+
+	return TRUE;
+}
+
+/**
+ * nm_setting_wireless_ap_security_compatible:
+ * @s_wireless: a #NMSettingWireless
+ * @s_wireless_sec: a #NMSettingWirelessSecurity or %NULL
+ * @ap_flags: the %NM80211ApFlags of the given access point
+ * @ap_wpa: the %NM80211ApSecurityFlags of the given access point's WPA
+ * capabilities
+ * @ap_rsn: the %NM80211ApSecurityFlags of the given access point's WPA2/RSN
+ * capabilities
+ * @ap_mode: the 802.11 mode of the AP, either Ad-Hoc or Infrastructure
+ *
+ * Given a #NMSettingWireless and an optional #NMSettingWirelessSecurity,
+ * determine if the configuration given by the settings is compatible with
+ * the security of an access point using that access point's capability flags
+ * and mode.  Useful for clients that wish to filter a set of connections
+ * against a set of access points and determine which connections are
+ * compatible with which access points.
+ *
+ * Returns: %TRUE if the given settings are compatible with the access point's
+ * security flags and mode, %FALSE if they are not.
+ */
+gboolean
+nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
+                                            NMSettingWirelessSecurity *s_wireless_sec,
+                                            NM80211ApFlags ap_flags,
+                                            NM80211ApSecurityFlags ap_wpa,
+                                            NM80211ApSecurityFlags ap_rsn,
+                                            NM80211Mode ap_mode)
+{
+	const char *key_mgmt = NULL, *cipher;
+	guint32 num, i;
+	gboolean found = FALSE;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE);
+
+	if (!s_wireless_sec) {
+		if (   (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
+		    || (ap_wpa != NM_802_11_AP_SEC_NONE)
+		    || (ap_rsn != NM_802_11_AP_SEC_NONE))
+			return FALSE;
+		return TRUE;
+	}
+
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
+	if (!key_mgmt)
+		return FALSE;
+
+	/* Static WEP */
+	if (!strcmp (key_mgmt, "none")) {
+		if (   !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
+		    || (ap_wpa != NM_802_11_AP_SEC_NONE)
+		    || (ap_rsn != NM_802_11_AP_SEC_NONE))
+			return FALSE;
+		return TRUE;
+	}
+
+	/* Adhoc WPA */
+	if (!strcmp (key_mgmt, "wpa-none")) {
+		if (ap_mode != NM_802_11_MODE_ADHOC)
+			return FALSE;
+		/* FIXME: validate ciphers if they're in the beacon */
+		return TRUE;
+	}
+
+	/* Adhoc WPA2 (ie, RSN IBSS) */
+	if (ap_mode == NM_802_11_MODE_ADHOC) {
+		if (strcmp (key_mgmt, "wpa-psk"))
+			return FALSE;
+
+		/* Ensure the AP has RSN PSK capability */
+		if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK))
+			return FALSE;
+
+		/* Fall through and check ciphers in generic WPA-PSK code */
+	}
+
+	/* Dynamic WEP or LEAP */
+	if (!strcmp (key_mgmt, "ieee8021x")) {
+		if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
+			return FALSE;
+
+		/* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */
+		if (ap_wpa != NM_802_11_AP_SEC_NONE) {
+			if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+				return FALSE;
+
+			/* quick check; can't use AP if it doesn't support at least one
+			 * WEP cipher in both pairwise and group suites.
+			 */
+			if (   !(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104))
+			    || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104)))
+				return FALSE;
+
+			/* Match at least one pairwise cipher with AP's capability if the
+			 * wireless-security setting explicitly lists pairwise ciphers
+			 */
+			num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec);
+			for (i = 0, found = FALSE; i < num; i++) {
+				cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i);
+				if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP40)))
+					break;
+				if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP104)))
+					break;
+			}
+			if (!found && num)
+				return FALSE;
+
+			/* Match at least one group cipher with AP's capability if the
+			 * wireless-security setting explicitly lists group ciphers
+			 */
+			num = nm_setting_wireless_security_get_num_groups (s_wireless_sec);
+			for (i = 0, found = FALSE; i < num; i++) {
+				cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i);
+				if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP40)))
+					break;
+				if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP104)))
+					break;
+			}
+			if (!found && num)
+				return FALSE;
+		}
+		return TRUE;
+	}
+
+	/* WPA[2]-PSK and WPA[2] Enterprise */
+	if (   !strcmp (key_mgmt, "wpa-psk")
+	    || !strcmp (key_mgmt, "wpa-eap")) {
+
+		if (!strcmp (key_mgmt, "wpa-psk")) {
+			if (   !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK)
+			    && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK))
+				return FALSE;
+		} else if (!strcmp (key_mgmt, "wpa-eap")) {
+			if (   !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+			    && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+				return FALSE;
+		}
+
+		// FIXME: should handle WPA and RSN separately here to ensure that
+		// if the Connection only uses WPA we don't match a cipher against
+		// the AP's RSN IE instead
+
+		/* Match at least one pairwise cipher with AP's capability if the
+		 * wireless-security setting explicitly lists pairwise ciphers
+		 */
+		num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec);
+		for (i = 0, found = FALSE; i < num; i++) {
+			cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i);
+			if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP)))
+				break;
+			if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP)))
+				break;
+		}
+		if (!found && num)
+			return FALSE;
+
+		/* Match at least one group cipher with AP's capability if the
+		 * wireless-security setting explicitly lists group ciphers
+		 */
+		num = nm_setting_wireless_security_get_num_groups (s_wireless_sec);
+		for (i = 0, found = FALSE; i < num; i++) {
+			cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i);
+
+			if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40)))
+				break;
+			if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104)))
+				break;
+			if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP)))
+				break;
+			if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP)))
+				break;
+		}
+		if (!found && num)
+			return FALSE;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * nm_setting_wireless_new:
+ *
+ * Creates a new #NMSettingWireless object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingWireless object
+ **/
+NMSetting *
+nm_setting_wireless_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRELESS, NULL);
+}
+
+/**
+ * nm_setting_wireless_get_ssid:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: (transfer none): the #NMSettingWireless:ssid property of the setting
+ **/
+GBytes *
+nm_setting_wireless_get_ssid (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->ssid;
+}
+
+/**
+ * nm_setting_wireless_get_mode:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mode property of the setting
+ **/
+const char *
+nm_setting_wireless_get_mode (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_wireless_get_band:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:band property of the setting
+ **/
+const char *
+nm_setting_wireless_get_band (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->band;
+}
+
+/**
+ * nm_setting_wireless_get_channel:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:channel property of the setting
+ **/
+guint32
+nm_setting_wireless_get_channel (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->channel;
+}
+
+/**
+ * nm_setting_wireless_get_bssid:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:bssid property of the setting
+ **/
+const char *
+nm_setting_wireless_get_bssid (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->bssid;
+}
+
+/**
+ * nm_setting_wireless_get_rate:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:rate property of the setting
+ **/
+guint32
+nm_setting_wireless_get_rate (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->rate;
+}
+
+/**
+ * nm_setting_wireless_get_tx_power:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:tx-power property of the setting
+ **/
+guint32
+nm_setting_wireless_get_tx_power (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->tx_power;
+}
+
+/**
+ * nm_setting_wireless_get_mac_address:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mac-address property of the setting
+ **/
+const char *
+nm_setting_wireless_get_mac_address (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->device_mac_address;
+}
+
+/**
+ * nm_setting_wireless_get_cloned_mac_address:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:cloned-mac-address property of the setting
+ **/
+const char *
+nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address;
+}
+
+/**
+ * nm_setting_wireless_get_mac_address_blacklist:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mac-address-blacklist property of the setting
+ **/
+const char * const *
+nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting)
+{
+	NMSettingWirelessPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	return (const char * const *) priv->mac_address_blacklist->data;
+}
+
+/**
+ * nm_setting_wireless_get_num_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the number of blacklisted MAC addresses
+ **/
+guint32
+nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist->len;
+}
+
+/**
+ * nm_setting_wireless_get_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: the zero-based index of the MAC address entry
+ *
+ * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
+ * at index @idx
+ **/
+const char *
+nm_setting_wireless_get_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+	NMSettingWirelessPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	g_return_val_if_fail (idx <= priv->mac_address_blacklist->len, NULL);
+
+	return g_array_index (priv->mac_address_blacklist, const char *, idx);
+}
+
+/**
+ * nm_setting_wireless_add_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
+ *
+ * Adds a new MAC address to the #NMSettingWireless:mac-address-blacklist property.
+ *
+ * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
+ * is invalid or was already present
+ **/
+gboolean
+nm_setting_wireless_add_mac_blacklist_item (NMSettingWireless *setting, const char *mac)
+{
+	NMSettingWirelessPrivate *priv;
+	const char *candidate;
+	int i;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!nm_utils_hwaddr_valid (mac, ETH_ALEN))
+		return FALSE;
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+		candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+		if (nm_utils_hwaddr_matches (mac, -1, candidate, -1))
+			return FALSE;
+	}
+
+	mac = nm_utils_hwaddr_canonical (mac, ETH_ALEN);
+	g_array_append_val (priv->mac_address_blacklist, mac);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+	return TRUE;
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: index number of the MAC address
+ *
+ * Removes the MAC address at index @idx from the blacklist.
+ **/
+void
+nm_setting_wireless_remove_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+	NMSettingWirelessPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	g_return_if_fail (idx < priv->mac_address_blacklist->len);
+
+	g_array_remove_index (priv->mac_address_blacklist, idx);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item_by_value:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
+ * the blacklist
+ *
+ * Removes the MAC address @mac from the blacklist.
+ *
+ * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_wireless_remove_mac_blacklist_item_by_value (NMSettingWireless *setting, const char *mac)
+{
+	NMSettingWirelessPrivate *priv;
+	const char *candidate;
+	int i;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+		candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+		if (!nm_utils_hwaddr_matches (mac, -1, candidate, -1)) {
+			g_array_remove_index (priv->mac_address_blacklist, i);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * nm_setting_wireless_clear_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Removes all blacklisted MAC addresses.
+ **/
+void
+nm_setting_wireless_clear_mac_blacklist_items (NMSettingWireless *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+	g_array_set_size (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wireless_get_mtu:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mtu property of the setting
+ **/
+guint32
+nm_setting_wireless_get_mtu (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mtu;
+}
+
+/**
+ * nm_setting_wireless_get_hidden:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:hidden property of the setting
+ **/
+gboolean
+nm_setting_wireless_get_hidden (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->hidden;
+}
+
+/**
+ * nm_setting_wireless_add_seen_bssid:
+ * @setting: the #NMSettingWireless
+ * @bssid: the new BSSID to add to the list
+ *
+ * Adds a new Wi-Fi AP's BSSID to the previously seen BSSID list of the setting.
+ * NetworkManager now tracks previously seen BSSIDs internally so this function
+ * no longer has much use. Actually, changes you make using this function will
+ * not be preserved.
+ *
+ * Returns: %TRUE if @bssid was already known, %FALSE if not
+ **/
+gboolean
+nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
+                                    const char *bssid)
+{
+	NMSettingWirelessPrivate *priv;
+	char *lower_bssid;
+	GSList *iter;
+	gboolean found = FALSE;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+	g_return_val_if_fail (bssid != NULL, FALSE);
+
+	lower_bssid = g_ascii_strdown (bssid, -1);
+	if (!lower_bssid)
+		return FALSE;
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+
+	for (iter = priv->seen_bssids; iter; iter = iter->next) {
+		if (!strcmp ((char *) iter->data, lower_bssid)) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (!found) {
+		priv->seen_bssids = g_slist_prepend (priv->seen_bssids, lower_bssid);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SEEN_BSSIDS);
+	} else
+		g_free (lower_bssid);
+
+	return !found;
+}
+
+/**
+ * nm_setting_wireless_get_num_seen_bssids:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the number of BSSIDs in the previously seen BSSID list
+ **/
+guint32
+nm_setting_wireless_get_num_seen_bssids (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return g_slist_length (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids);
+}
+
+/**
+ * nm_setting_wireless_get_seen_bssid:
+ * @setting: the #NMSettingWireless
+ * @i: index of a BSSID in the previously seen BSSID list
+ *
+ * Returns: the BSSID at index @i
+ **/
+const char *
+nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting,
+                                    guint32 i)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	return (const char *) g_slist_nth_data (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids, i);
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	const char *valid_modes[] = { NM_SETTING_WIRELESS_MODE_INFRA, NM_SETTING_WIRELESS_MODE_ADHOC, NM_SETTING_WIRELESS_MODE_AP, NULL };
+	const char *valid_bands[] = { "a", "bg", NULL };
+	GSList *iter;
+	int i;
+	gsize length;
+
+	if (!priv->ssid) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
+		return FALSE;
+	}
+
+	length = g_bytes_get_size (priv->ssid);
+	if (length == 0 || length > 32) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("SSID length is out of range <1-32> bytes"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
+		return FALSE;
+	}
+
+	if (priv->mode && !_nm_utils_string_in_list (priv->mode, valid_modes)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid Wi-Fi mode"),
+		             priv->mode);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MODE);
+		return FALSE;
+	}
+
+	if (priv->band && !_nm_utils_string_in_list (priv->band, valid_bands)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid band"),
+		             priv->band);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BAND);
+		return FALSE;
+	}
+
+	if (priv->channel && !priv->band) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_MISSING_PROPERTY,
+		             _("'%s' requires setting '%s' property"),
+		             NM_SETTING_WIRELESS_CHANNEL, NM_SETTING_WIRELESS_BAND);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BAND);
+		return FALSE;
+	}
+
+	if (priv->channel) {
+		if (!nm_utils_wifi_is_channel_valid (priv->channel, priv->band)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%d' is not a valid channel"),
+			             priv->channel);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CHANNEL);
+			return FALSE;
+		}
+	}
+
+	if (priv->bssid && !nm_utils_hwaddr_valid (priv->bssid, ETH_ALEN)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BSSID);
+		return FALSE;
+	}
+
+	if (priv->device_mac_address && !nm_utils_hwaddr_valid (priv->device_mac_address, ETH_ALEN)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS);
+		return FALSE;
+	}
+
+	if (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,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS);
+		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);
+
+		if (!nm_utils_hwaddr_valid (mac, ETH_ALEN)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid MAC address"),
+			             mac);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+			return FALSE;
+		}
+	}
+
+	for (iter = priv->seen_bssids; iter; iter = iter->next) {
+		if (!nm_utils_hwaddr_valid (iter->data, ETH_ALEN)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid MAC address"),
+			             (const char *) iter->data);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SEEN_BSSIDS);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+static GVariant *
+nm_setting_wireless_get_security (NMSetting    *setting,
+                                  NMConnection *connection,
+                                  const char   *property_name)
+{
+	if (nm_connection_get_setting_wireless_security (connection))
+		return g_variant_new_string (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	else
+		return NULL;
+}
+
+static void
+clear_blacklist_item (char **item_p)
+{
+	g_free (*item_p);
+}
+
+static void
+nm_setting_wireless_init (NMSettingWireless *setting)
+{
+	NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+
+	/* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */
+	priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *));
+	g_array_set_clear_func (priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+
+	g_free (priv->mode);
+	g_free (priv->band);
+
+	if (priv->ssid)
+		g_bytes_unref (priv->ssid);
+	g_free (priv->bssid);
+	g_free (priv->device_mac_address);
+	g_free (priv->cloned_mac_address);
+	g_array_unref (priv->mac_address_blacklist);
+	g_slist_free_full (priv->seen_bssids, g_free);
+
+	G_OBJECT_CLASS (nm_setting_wireless_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+	const char * const *blacklist;
+	const char *mac;
+	int i;
+
+	switch (prop_id) {
+	case PROP_SSID:
+		if (priv->ssid)
+			g_bytes_unref (priv->ssid);
+		priv->ssid = g_value_dup_boxed (value);
+		break;
+	case PROP_MODE:
+		g_free (priv->mode);
+		priv->mode = g_value_dup_string (value);
+		break;
+	case PROP_BAND:
+		g_free (priv->band);
+		priv->band = g_value_dup_string (value);
+		break;
+	case PROP_CHANNEL:
+		priv->channel = g_value_get_uint (value);
+		break;
+	case PROP_BSSID:
+		g_free (priv->bssid);
+		priv->bssid = g_value_dup_string (value);
+		break;
+	case PROP_RATE:
+		priv->rate = g_value_get_uint (value);
+		break;
+	case PROP_TX_POWER:
+		priv->tx_power = g_value_get_uint (value);
+		break;
+	case PROP_MAC_ADDRESS:
+		g_free (priv->device_mac_address);
+		priv->device_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+		                                                                  ETH_ALEN);
+		break;
+	case PROP_CLONED_MAC_ADDRESS:
+		g_free (priv->cloned_mac_address);
+		priv->cloned_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+		                                                                  ETH_ALEN);
+		break;
+	case PROP_MAC_ADDRESS_BLACKLIST:
+		blacklist = g_value_get_boxed (value);
+		g_array_set_size (priv->mac_address_blacklist, 0);
+		if (blacklist && *blacklist) {
+			for (i = 0; blacklist[i]; i++) {
+				mac = _nm_utils_hwaddr_canonical_or_invalid (blacklist[i], ETH_ALEN);
+				g_array_append_val (priv->mac_address_blacklist, mac);
+			}
+		}
+		break;
+	case PROP_MTU:
+		priv->mtu = g_value_get_uint (value);
+		break;
+	case PROP_SEEN_BSSIDS:
+		g_slist_free_full (priv->seen_bssids, g_free);
+		priv->seen_bssids = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+		break;
+	case PROP_HIDDEN:
+		priv->hidden = g_value_get_boolean (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMSettingWireless *setting = NM_SETTING_WIRELESS (object);
+	NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_SSID:
+		g_value_set_boxed (value, nm_setting_wireless_get_ssid (setting));
+		break;
+	case PROP_MODE:
+		g_value_set_string (value, nm_setting_wireless_get_mode (setting));
+		break;
+	case PROP_BAND:
+		g_value_set_string (value, nm_setting_wireless_get_band (setting));
+		break;
+	case PROP_CHANNEL:
+		g_value_set_uint (value, nm_setting_wireless_get_channel (setting));
+		break;
+	case PROP_BSSID:
+		g_value_set_string (value, nm_setting_wireless_get_bssid (setting));
+		break;
+	case PROP_RATE:
+		g_value_set_uint (value, nm_setting_wireless_get_rate (setting));
+		break;
+	case PROP_TX_POWER:
+		g_value_set_uint (value, nm_setting_wireless_get_tx_power (setting));
+		break;
+	case PROP_MAC_ADDRESS:
+		g_value_set_string (value, nm_setting_wireless_get_mac_address (setting));
+		break;
+	case PROP_CLONED_MAC_ADDRESS:
+		g_value_set_string (value, nm_setting_wireless_get_cloned_mac_address (setting));
+		break;
+	case PROP_MAC_ADDRESS_BLACKLIST:
+		g_value_set_boxed (value, (char **) priv->mac_address_blacklist->data);
+		break;
+	case PROP_MTU:
+		g_value_set_uint (value, nm_setting_wireless_get_mtu (setting));
+		break;
+	case PROP_SEEN_BSSIDS:
+		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->seen_bssids));
+		break;
+	case PROP_HIDDEN:
+		g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	g_type_class_add_private (setting_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;
+
+	/* Properties */
+	/**
+	 * NMSettingWireless:ssid:
+	 *
+	 * SSID of the Wi-Fi network. Must be specified.
+	 **/
+	/* ---keyfile---
+	 * property: ssid
+	 * format: string (or decimal-byte list - obsolete)
+	 * description: SSID of Wi-Fi network.
+	 * example: ssid=Quick Net
+	 * ---end---
+	 * ---ifcfg-rh---
+	 * property: ssid
+	 * variable: ESSID
+	 * description: SSID of Wi-Fi network.
+	 * example: ESSID="Quick Net"
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_SSID,
+		 g_param_spec_boxed (NM_SETTING_WIRELESS_SSID, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:mode:
+	 *
+	 * Wi-Fi network mode; one of "infrastructure", "adhoc" or "ap".  If blank,
+	 * infrastructure is assumed.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: mode
+	 * variable: MODE
+	 * values: Ad-Hoc, Managed (Auto)  [case insensitive]
+	 * description: Wi-Fi network mode.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_string (NM_SETTING_WIRELESS_MODE, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:band:
+	 *
+	 * 802.11 frequency band of the network.  One of "a" for 5GHz 802.11a or
+	 * "bg" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network
+	 * to the specific band, i.e. if "a" is specified, the device will not
+	 * associate with the same network in the 2.4GHz band even if the network's
+	 * settings are compatible.  This setting depends on specific driver
+	 * capability and may not work with all drivers.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: band
+	 * variable: BAND(+)
+	 * values: a, bg
+	 * description: BAND alone is honored, but CHANNEL overrides BAND since it
+	 *   implies a band.
+	 * example: BAND=bg
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_BAND,
+		 g_param_spec_string (NM_SETTING_WIRELESS_BAND, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:channel:
+	 *
+	 * Wireless channel to use for the Wi-Fi connection.  The device will only
+	 * join (or create for Ad-Hoc networks) a Wi-Fi network on the specified
+	 * channel.  Because channel numbers overlap between bands, this property
+	 * also requires the "band" property to be set.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: channel
+	 * variable: CHANNEL
+	 * description: Channel used for the Wi-Fi communication.
+	 *   Channels greater than 14 mean "a" band, otherwise the
+	 *   band is "bg".
+	 * example: CHANNEL=6
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_CHANNEL,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_CHANNEL, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:bssid:
+	 *
+	 * If specified, directs the device to only associate with the given access
+	 * point.  This capability is highly driver dependent and not supported by
+	 * all devices.  Note: this property does not control the BSSID used when
+	 * creating an Ad-Hoc network and is unlikely to in the future.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: bssid
+	 * variable: BSSID(+)
+	 * description: Restricts association only to a single AP.
+	 * example: BSSID=00:1E:BD:64:83:21
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_BSSID,
+		 g_param_spec_string (NM_SETTING_WIRELESS_BSSID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_BSSID,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
+
+	/**
+	 * NMSettingWireless:rate:
+	 *
+	 * If non-zero, directs the device to only use the specified bitrate for
+	 * communication with the access point.  Units are in Kb/s, ie 5500 = 5.5
+	 * Mbit/s.  This property is highly driver dependent and not all devices
+	 * support setting a static bitrate.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: rate
+	 * variable: (none)
+	 * description: This property is not handled by ifcfg-rh plugin.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_RATE,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_RATE, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_FUZZY_IGNORE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:tx-power:
+	 *
+	 * If non-zero, directs the device to use the specified transmit power.
+	 * Units are dBm.  This property is highly driver dependent and not all
+	 * devices support setting a static transmit power.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: tx-power
+	 * variable: (none)
+	 * description: This property is not handled by ifcfg-rh plugin.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_TX_POWER,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_TX_POWER, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_FUZZY_IGNORE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:mac-address:
+	 *
+	 * If specified, this connection will only apply to the Wi-Fi device whose
+	 * permanent MAC address matches. This property does not change the MAC
+	 * address of the device (i.e. MAC spoofing).
+	 **/
+	/* ---keyfile---
+	 * property: mac-address
+	 * format: ususal hex-digits-and-colons notation
+	 * description: MAC address in traditional hex-digits-and-colons notation
+	 *   (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete)
+	 *   (e.g. 0;34;104;18;121;162).
+	 * ---end---
+	 * ---ifcfg-rh---
+	 * property: mac-address
+	 * variable: HWADDR
+	 * description: Hardware address of the device in traditional hex-digits-and-colons
+	 *    notation (e.g. 00:22:68:14:5A:05).
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MAC_ADDRESS,
+		 g_param_spec_string (NM_SETTING_WIRELESS_MAC_ADDRESS, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
+
+	/**
+	 * 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.
+	 **/
+	/* ---keyfile---
+	 * property: cloned-mac-address
+	 * format: ususal hex-digits-and-colons notation
+	 * description: Cloned MAC address in traditional hex-digits-and-colons notation
+	 *   (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete)
+	 *   (e.g. 0;34;104;18;121;178).
+	 * ---end---
+	 * ---ifcfg-rh---
+	 * property: cloned-mac-address
+	 * variable: MACADDR
+	 * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons
+	 *    notation (e.g. 00:22:68:14:5A:99).
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_CLONED_MAC_ADDRESS,
+		 g_param_spec_string (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "", "",
+		                      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);
+
+	/**
+	 * NMSettingWireless:mac-address-blacklist:
+	 *
+	 * A list of permanent MAC addresses of Wi-Fi devices to which this
+	 * connection should never apply.  Each MAC address should be given in the
+	 * standard hex-digits-and-colons notation (eg "00:11:22:33:44:55").
+	 **/
+	/* ---keyfile---
+	 * property: mac-address-blacklist
+	 * format: list of MACs (separated with semicolons)
+	 * description: MAC address blacklist.
+	 * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78
+	 * ---end---
+	 * ---ifcfg-rh---
+	 * property: mac-address-blacklist
+	 * variable: HWADDR_BLACKLIST(+)
+	 * description: It denies usage of the connection for any device whose address
+	 *   is listed.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MAC_ADDRESS_BLACKLIST,
+		 g_param_spec_boxed (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     NM_SETTING_PARAM_FUZZY_IGNORE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:seen-bssids:
+	 *
+	 * A list of BSSIDs (each BSSID formatted as a MAC address like
+	 * "00:11:22:33:44:55") that have been detected as part of the Wi-Fi
+	 * network.  NetworkManager internally tracks previously seen BSSIDs. The
+	 * property is only meant for reading and reflects the BSSID list of
+	 * NetworkManager. The changes you make to this property will not be
+	 * preserved.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: seen-bssids
+	 * variable: (none)
+	 * description: This property is not handled by ifcfg-rh plugin.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_SEEN_BSSIDS,
+		 g_param_spec_boxed (NM_SETTING_WIRELESS_SEEN_BSSIDS, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     NM_SETTING_PARAM_FUZZY_IGNORE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:mtu:
+	 *
+	 * If non-zero, only transmit packets of the specified size or smaller,
+	 * breaking larger packets up into multiple Ethernet frames.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: mtu
+	 * variable: MTU
+	 * description: MTU of the wireless interface.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MTU,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_MTU, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_FUZZY_IGNORE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:hidden:
+	 *
+	 * If %TRUE, indicates this network is a non-broadcasting network that hides
+	 * its SSID.  In this case various workarounds may take place, such as
+	 * probe-scanning the SSID for more reliable network discovery.  However,
+	 * these workarounds expose inherent insecurities with hidden SSID networks,
+	 * and thus hidden SSID networks should be used with caution.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: hidden
+	 * variable: SSID_HIDDEN(+)
+	 * description: Whether the network hides the SSID.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_HIDDEN,
+		 g_param_spec_boolean (NM_SETTING_WIRELESS_HIDDEN, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/* Compatibility for deprecated property */
+	/* ---ifcfg-rh---
+	 * property: security
+	 * variable: (none)
+	 * description: This property is deprecated and not handled by ifcfg-rh-plugin.
+	 * ---end---
+	 * ---dbus---
+	 * property: security
+	 * description: This property is deprecated, but can be set to the value
+	 *   '802-11-wireless-security' when a wireless security setting is also
+	 *   present in the connection dictionary, for compatibility with very old
+	 *   NetworkManager daemons.
+	 * ---end---
+	 */
+	_nm_setting_class_add_dbus_only_property (parent_class, "security",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          nm_setting_wireless_get_security, NULL);
+}