Skip to contentSkip to conversation

PMKSA support

RFC Superseded Samuel Ortiz 3 participants 10 messages Nov 24, 2009

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover PMKSA support

Hi John,

This patchset is an RFC for a new PMKSA API. This is needed for fullmac devices that run firmwares which set the re-association frames IEs. Those devices need to get a correct PMKID from wpa_supplicant in order to do faster WPA2 roaming. mac80211 based drivers wont need to use this API, wpa_supplicant does all the work for them.

The patchset defines the nl80211 API, adds a wext compatibility handler, and finally provides the corresponding iwmc3200wifi implementation.

Samuel Ortiz (3):
nl80211: PMKSA caching support
cfg80211: Add PMKSA wext compatibility handler
iwmc3200wifi: Implement cfg80211 PMKSA API

 drivers/net/wireless/iwmc3200wifi/cfg80211.c |   30 +++++++
 drivers/net/wireless/iwmc3200wifi/commands.c |   22 +++++
 drivers/net/wireless/iwmc3200wifi/commands.h |   13 +++
 drivers/net/wireless/iwmc3200wifi/umac.h     |    1 +
 include/linux/ieee80211.h                    |    2 +
 include/linux/nl80211.h                      |    6 ++
 include/net/cfg80211.h                       |   26 ++++++
 net/wireless/nl80211.c                       |  117 ++++++++++++++++++++++++++
 net/wireless/wext-compat.c                   |   42 +++++++++
 9 files changed, 259 insertions(+), 0 deletions(-)
#1 lore raw

RFC 1/3 nl80211: PMKSA caching support

This is an interface to set, delete and flush PMKIDs through nl80211. Main users would be fullmac devices which firmwares are capable of generating the RSN IEs for the re-association requests, e.g. iwmc3200wifi.

---
 include/linux/ieee80211.h |    2 +
 include/linux/nl80211.h   |    6 ++
 include/net/cfg80211.h    |   26 ++++++++++
 net/wireless/nl80211.c    |  117 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 151 insertions(+), 0 deletions(-)
include/linux/ieee80211.h +2 -0
index afa8e0a..d9724a2 100644
@@ -1266,6 +1266,8 @@ enum ieee80211_sa_query_action {
 
 #define WLAN_MAX_KEY_LEN		32
 
+#define WLAN_PMKID_LEN			16
+
 /**
  * ieee80211_get_qos_ctl - get pointer to qos control bytes
  * @hdr: the frame
include/linux/nl80211.h +6 -0
index 45db17f..3b85d76 100644
@@ -349,6 +349,10 @@ enum nl80211_commands {
 	NL80211_CMD_GET_SURVEY,
 	NL80211_CMD_NEW_SURVEY_RESULTS,
 
+	NL80211_CMD_SET_PMKSA,
+	NL80211_CMD_DEL_PMKSA,
+	NL80211_CMD_FLUSH_PMKSA,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -732,6 +736,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_SURVEY_INFO,
 
+	NL80211_ATTR_PMKID,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
include/net/cfg80211.h +26 -0
index a6492e9..6211372 100644
@@ -871,6 +871,19 @@ struct cfg80211_bitrate_mask {
 	u32 fixed;   /* fixed bitrate, 0 == not fixed */
 	u32 maxrate; /* in kbps, 0 == no limit */
 };
+/**
+ * struct cfg80211_pmksa - PMK Security Association
+ *
+ * This structure is passed to the set/del_pmksa() method for PMKSA
+ * caching.
+ *
+ * @bssid: The AP's BSSID.
+ * @pmkid: The PMK material itself.
+ */
+struct cfg80211_pmksa {
+	u8 *bssid;
+	u8 *pmkid;
+};
 
 /**
  * struct cfg80211_ops - backend description for wireless configuration
@@ -976,6 +989,13 @@ struct cfg80211_bitrate_mask {
  * @dump_survey: get site survey information.
  *
  * @testmode_cmd: run a test mode command
+ *
+ * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
+ *	devices running firmwares capable of generating the (re) association
+ *	RSN IE. It allows for faster roaming between WPA2 BSSIDs.
+ * @del_pmksa: Delete a cached PMKID.
+ * @flush_pmksa: Flush all cached PMKIDs.
+ *
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -1097,6 +1117,12 @@ struct cfg80211_ops {
 	int	(*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
 			int idx, struct survey_info *info);
 
+	int	(*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+			     struct cfg80211_pmksa *pmksa);
+	int	(*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+			     struct cfg80211_pmksa *pmksa);
+	int	(*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
+
 	/* some temporary stuff to finish wext */
 	int	(*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
 				  bool enabled, int timeout);
net/wireless/nl80211.c +117 -0

141 lines not on this page · raw message

Signature · 1 line
1.6.3.3
#2 lore raw

RFC 2/3 cfg80211: Add PMKSA wext compatibility handler

With the addition of the *_pmksa cfg80211 ops, we can now add the corresponding wireless extensions compatibility handler.

---
 net/wireless/wext-compat.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)
net/wireless/wext-compat.c +42 -0
index 29091ac..7e7985e 100644
@@ -1401,6 +1401,47 @@ int cfg80211_wext_giwessid(struct net_device *dev,
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
 
+int cfg80211_wext_siwpmksa(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *data, char *extra)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct cfg80211_pmksa cfg_pmksa;
+	struct iw_pmksa* pmksa = (struct iw_pmksa *)extra;
+
+	memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
+
+	if (wdev->iftype != NL80211_IFTYPE_STATION)
+		return -EINVAL;
+
+	cfg_pmksa.bssid = pmksa->bssid.sa_data;
+	cfg_pmksa.pmkid = pmksa->pmkid;
+
+	switch (pmksa->cmd) {
+	case IW_PMKSA_ADD:
+		if (!rdev->ops->set_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+
+	case IW_PMKSA_REMOVE:
+		if (!rdev->ops->del_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+
+	case IW_PMKSA_FLUSH:
+		if (!rdev->ops->flush_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const iw_handler cfg80211_handlers[] = {
 	[IW_IOCTL_IDX(SIOCGIWNAME)]	= (iw_handler) cfg80211_wext_giwname,
 	[IW_IOCTL_IDX(SIOCSIWFREQ)]	= (iw_handler) cfg80211_wext_siwfreq,
@@ -1433,6 +1474,7 @@ static const iw_handler cfg80211_handlers[] = {
 	[IW_IOCTL_IDX(SIOCSIWAUTH)]	= (iw_handler) cfg80211_wext_siwauth,
 	[IW_IOCTL_IDX(SIOCGIWAUTH)]	= (iw_handler) cfg80211_wext_giwauth,
 	[IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
+	[IW_IOCTL_IDX(SIOCSIWPMKSA)]	= (iw_handler) cfg80211_wext_siwpmksa,
 };
 
 const struct iw_handler_def cfg80211_wext_handler = {
Signature · 1 line
1.6.3.3
#3 lore raw

RFC 3/3 iwmc3200wifi: Implement cfg80211 PMKSA API

We need to implement the PMKSA API for proper WPA2 pre-auth and fast re-association. Our fullmac device generates all (re-)assoc IEs, and thus it needs the right PMKIDs. With this implementation we now get them from wpa_supplicant.

---
 drivers/net/wireless/iwmc3200wifi/cfg80211.c |   30 ++++++++++++++++++++++++++
 drivers/net/wireless/iwmc3200wifi/commands.c |   22 +++++++++++++++++++
 drivers/net/wireless/iwmc3200wifi/commands.h |   13 +++++++++++
 drivers/net/wireless/iwmc3200wifi/umac.h     |    1 +
 4 files changed, 66 insertions(+), 0 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +30 -0
index 7cfc2c0..c74f9f9 100644
@@ -725,6 +725,33 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 				       CFG_POWER_INDEX, iwm->conf.power_index);
 }
 
+int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			   struct cfg80211_pmksa *pmksa)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
+}
+
+int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			   struct cfg80211_pmksa *pmksa)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
+}
+
+int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+	struct cfg80211_pmksa pmksa;
+
+	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
+
+	return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
+}
+
+
 static struct cfg80211_ops iwm_cfg80211_ops = {
 	.change_virtual_intf = iwm_cfg80211_change_iface,
 	.add_key = iwm_cfg80211_add_key,
@@ -741,6 +768,9 @@ static struct cfg80211_ops iwm_cfg80211_ops = {
 	.set_tx_power = iwm_cfg80211_set_txpower,
 	.get_tx_power = iwm_cfg80211_get_txpower,
 	.set_power_mgmt = iwm_cfg80211_set_power_mgmt,
+	.set_pmksa = iwm_cfg80211_set_pmksa,
+	.del_pmksa = iwm_cfg80211_del_pmksa,
+	.flush_pmksa = iwm_cfg80211_flush_pmksa,
 };
 
 static const u32 cipher_suites[] = {
drivers/net/wireless/iwmc3200wifi/commands.c +22 -0
index 46ca7c5..bd06307 100644
@@ -960,3 +960,25 @@ int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
 				 sizeof(struct iwm_umac_cmd_stop_resume_tx));
 
 }
+
+int iwm_send_pmkid_update(struct iwm_priv *iwm,
+			  struct cfg80211_pmksa *pmksa, u32 command)
+{
+	struct iwm_umac_pmkid_update update;
+	int ret;
+
+	memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
+
+	update.command = cpu_to_le32(command);
+	memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
+	memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
+
+	ret = iwm_send_wifi_if_cmd(iwm, &update,
+				   sizeof(struct iwm_umac_pmkid_update), 0);
+	if (ret) {
+		IWM_ERR(iwm, "PMKID update command failed\n");
+		return ret;
+	}
+
+	return 0;
+}
drivers/net/wireless/iwmc3200wifi/commands.h +13 -0
index 95cdf94..06af055 100644
@@ -458,6 +458,17 @@ struct iwm_umac_cmd_stop_resume_tx {
 	u16 reserved;
 } __attribute__ ((packed));
 
+#define IWM_CMD_PMKID_ADD   1
+#define IWM_CMD_PMKID_DEL   2
+#define IWM_CMD_PMKID_FLUSH 3
+
+struct iwm_umac_pmkid_update {
+	__le32 command;
+	u8 bssid[ETH_ALEN];
+	__le16 reserved;
+	u8 pmkid[WLAN_PMKID_LEN];
+} __attribute__ ((packed));
+
 /* LMAC commands */
 int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
 int iwm_send_prio_table(struct iwm_priv *iwm);
@@ -488,6 +499,8 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
 int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
 int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
 				 struct iwm_umac_notif_stop_resume_tx *ntf);
+int iwm_send_pmkid_update(struct iwm_priv *iwm,
+			  struct cfg80211_pmksa *pmksa, u32 command);
 
 /* UDMA commands */
 int iwm_target_reset(struct iwm_priv *iwm);
drivers/net/wireless/iwmc3200wifi/umac.h +1 -0
index 70094bf..24c7c7a 100644
@@ -298,6 +298,7 @@ struct iwm_udma_out_wifi_hdr {
 #define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID                0x1B
 #define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE            0x1C
 #define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS          0x1E
+#define UMAC_WIFI_IF_CMD_PMKID_UPDATE                    0x1F
 #define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER                  0x20
 
 /* UMAC WiFi interface ports */
Signature · 1 line
1.6.3.3
#4 lore raw

PATCH v2 3/3 iwmc3200wifi: Implement cfg80211 PMKSA API

We need to implement the PMKSA API for proper WPA2 pre-auth and fast re-association. Our fullmac device generates all (re-)assoc IEs, and thus it needs the right PMKIDs. With this implementation we now get them from wpa_supplicant.

---

v2: Set wiphy->max_num_pmkids

 drivers/net/wireless/iwmc3200wifi/cfg80211.c |   31 ++++++++++++++++++++++++++
 drivers/net/wireless/iwmc3200wifi/commands.c |   22 ++++++++++++++++++
 drivers/net/wireless/iwmc3200wifi/commands.h |   13 +++++++++++
 drivers/net/wireless/iwmc3200wifi/umac.h     |    2 +
 4 files changed, 68 insertions(+), 0 deletions(-)
drivers/net/wireless/iwmc3200wifi/cfg80211.c +31 -0
index 7cfc2c0..7c4f44a 100644
@@ -725,6 +725,33 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
 				       CFG_POWER_INDEX, iwm->conf.power_index);
 }
 
+int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			   struct cfg80211_pmksa *pmksa)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
+}
+
+int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
+			   struct cfg80211_pmksa *pmksa)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+
+	return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
+}
+
+int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
+{
+	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
+	struct cfg80211_pmksa pmksa;
+
+	memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
+
+	return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
+}
+
+
 static struct cfg80211_ops iwm_cfg80211_ops = {
 	.change_virtual_intf = iwm_cfg80211_change_iface,
 	.add_key = iwm_cfg80211_add_key,
@@ -741,6 +768,9 @@ static struct cfg80211_ops iwm_cfg80211_ops = {
 	.set_tx_power = iwm_cfg80211_set_txpower,
 	.get_tx_power = iwm_cfg80211_get_txpower,
 	.set_power_mgmt = iwm_cfg80211_set_power_mgmt,
+	.set_pmksa = iwm_cfg80211_set_pmksa,
+	.del_pmksa = iwm_cfg80211_del_pmksa,
+	.flush_pmksa = iwm_cfg80211_flush_pmksa,
 };
 
 static const u32 cipher_suites[] = {
@@ -786,6 +816,7 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
 
 	set_wiphy_dev(wdev->wiphy, dev);
 	wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
+	wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
 	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 				       BIT(NL80211_IFTYPE_ADHOC);
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
drivers/net/wireless/iwmc3200wifi/commands.c +22 -0
index 46ca7c5..bd06307 100644
@@ -960,3 +960,25 @@ int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
 				 sizeof(struct iwm_umac_cmd_stop_resume_tx));
 
 }
+
+int iwm_send_pmkid_update(struct iwm_priv *iwm,
+			  struct cfg80211_pmksa *pmksa, u32 command)
+{
+	struct iwm_umac_pmkid_update update;
+	int ret;
+
+	memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
+
+	update.command = cpu_to_le32(command);
+	memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
+	memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
+
+	ret = iwm_send_wifi_if_cmd(iwm, &update,
+				   sizeof(struct iwm_umac_pmkid_update), 0);
+	if (ret) {
+		IWM_ERR(iwm, "PMKID update command failed\n");
+		return ret;
+	}
+
+	return 0;
+}
drivers/net/wireless/iwmc3200wifi/commands.h +13 -0
index 95cdf94..06af055 100644
@@ -458,6 +458,17 @@ struct iwm_umac_cmd_stop_resume_tx {
 	u16 reserved;
 } __attribute__ ((packed));
 
+#define IWM_CMD_PMKID_ADD   1
+#define IWM_CMD_PMKID_DEL   2
+#define IWM_CMD_PMKID_FLUSH 3
+
+struct iwm_umac_pmkid_update {
+	__le32 command;
+	u8 bssid[ETH_ALEN];
+	__le16 reserved;
+	u8 pmkid[WLAN_PMKID_LEN];
+} __attribute__ ((packed));
+
 /* LMAC commands */
 int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
 int iwm_send_prio_table(struct iwm_priv *iwm);
@@ -488,6 +499,8 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
 int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
 int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
 				 struct iwm_umac_notif_stop_resume_tx *ntf);
+int iwm_send_pmkid_update(struct iwm_priv *iwm,
+			  struct cfg80211_pmksa *pmksa, u32 command);
 
 /* UDMA commands */
 int iwm_target_reset(struct iwm_priv *iwm);
drivers/net/wireless/iwmc3200wifi/umac.h +2 -0
index 70094bf..7f54a14 100644
@@ -298,6 +298,7 @@ struct iwm_udma_out_wifi_hdr {
 #define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID                0x1B
 #define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE            0x1C
 #define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS          0x1E
+#define UMAC_WIFI_IF_CMD_PMKID_UPDATE                    0x1F
 #define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER                  0x20
 
 /* UMAC WiFi interface ports */
@@ -771,6 +772,7 @@ struct iwm_umac_notif_stop_resume_tx {
 	__le16 stop_resume_tid_msk; /* tid bitmask */
 } __attribute__ ((packed));
 
+#define UMAC_MAX_NUM_PMKIDS 4
 
 /* WiFi interface wrapper header */
 struct iwm_umac_wifi_if {
Signature · 5 lines
1.6.3.3

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
#5 lore raw

PATCH v2 2/3 cfg80211: Add PMKSA wext compatibility handler

In reply to Samuel Ortiz

With the addition of the *_pmksa cfg80211 ops, we can now add the corresponding wireless extensions compatibility handler.

---

v2: Fixed a coding style issue thanks to johill's eagle eye.

 net/wireless/wext-compat.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)
net/wireless/wext-compat.c +42 -0
index 29091ac..584eb48 100644
@@ -1401,6 +1401,47 @@ int cfg80211_wext_giwessid(struct net_device *dev,
 }
 EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
 
+int cfg80211_wext_siwpmksa(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *data, char *extra)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct cfg80211_pmksa cfg_pmksa;
+	struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
+
+	memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
+
+	if (wdev->iftype != NL80211_IFTYPE_STATION)
+		return -EINVAL;
+
+	cfg_pmksa.bssid = pmksa->bssid.sa_data;
+	cfg_pmksa.pmkid = pmksa->pmkid;
+
+	switch (pmksa->cmd) {
+	case IW_PMKSA_ADD:
+		if (!rdev->ops->set_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+
+	case IW_PMKSA_REMOVE:
+		if (!rdev->ops->del_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
+
+	case IW_PMKSA_FLUSH:
+		if (!rdev->ops->flush_pmksa)
+			return -EOPNOTSUPP;
+
+		return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const iw_handler cfg80211_handlers[] = {
 	[IW_IOCTL_IDX(SIOCGIWNAME)]	= (iw_handler) cfg80211_wext_giwname,
 	[IW_IOCTL_IDX(SIOCSIWFREQ)]	= (iw_handler) cfg80211_wext_siwfreq,
@@ -1433,6 +1474,7 @@ static const iw_handler cfg80211_handlers[] = {
 	[IW_IOCTL_IDX(SIOCSIWAUTH)]	= (iw_handler) cfg80211_wext_siwauth,
 	[IW_IOCTL_IDX(SIOCGIWAUTH)]	= (iw_handler) cfg80211_wext_giwauth,
 	[IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
+	[IW_IOCTL_IDX(SIOCSIWPMKSA)]	= (iw_handler) cfg80211_wext_siwpmksa,
 };
 
 const struct iw_handler_def cfg80211_wext_handler = {
Signature · 5 lines
1.6.3.3

-- 
Intel Open Source Technology Centre
http://oss.intel.com/
#6 lore raw

Re: [RFC 1/3] nl80211: PMKSA caching support

In reply to Samuel Ortiz
Quoted 3 lines · Samuel Ortiz

This is an interface to set, delete and flush PMKIDs through nl80211. Main users would be fullmac devices which firmwares are capable of generating the RSN IEs for the re-association requests, e.g. iwmc3200wifi.

Is there a maximum number of PMKSA cache entries that the driver can handle? If so, it might be useful to provide a mechanism to indicate that limit (e.g., something similar to NL80211_ATTR_MAX_NUM_SCAN_SSIDS).

Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
#7 lore raw

Re: [RFC 1/3] nl80211: PMKSA caching support

Hi Jouni,

Quoted 8 lines · Jouni Malinen
Quoted 3 lines · Samuel Ortiz

This is an interface to set, delete and flush PMKIDs through nl80211. Main users would be fullmac devices which firmwares are capable of generating the RSN IEs for the re-association requests, e.g. iwmc3200wifi.

Is there a maximum number of PMKSA cache entries that the driver can handle? If so, it might be useful to provide a mechanism to indicate that limit (e.g., something similar to NL80211_ATTR_MAX_NUM_SCAN_SSIDS).

Good point. I'll add that to the patch.

Cheers,
Samuel.

Quoted 2 lines
Signature · 1 line
Jouni Malinen                                            PGP id EFC895FA
Signature · 2 lines
Intel Open Source Technology Centre
http://oss.intel.com/
#8 lore raw

Re: [RFC 1/3] nl80211: PMKSA caching support

In reply to Samuel Ortiz

Hi Samuel,

net/wireless/nl80211.c static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, · line 568

Quoted 8 lines

/* policy for the attributes */

net/wireless/nl80211.c +3 -0
@@ -561,6 +563,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 	CMD(deauth, DEAUTHENTICATE);
 	CMD(disassoc, DISASSOCIATE);
 	CMD(join_ibss, JOIN_IBSS);
+	CMD(set_pmksa, SET_PMKSA);
+	CMD(del_pmksa, DEL_PMKSA);
+	CMD(flush_pmksa, FLUSH_PMKSA);

once these have been accepted, don't forget to send a patch for iw that actually prints out the supported command list.

Regards

Marcel

#9 lore raw

PATCH v2 1/3 nl80211: PMKSA caching support

In reply to Samuel Ortiz

This is an interface to set, delete and flush PMKIDs through nl80211. Main users would be fullmac devices which firmwares are capable of generating the RSN IEs for the re-association requests, e.g. iwmc3200wifi.

---

v2: Added NL80211_ATTR_MAX_NUM_PMKIDS attribute

 include/linux/ieee80211.h |    2 +
 include/linux/nl80211.h   |   11 ++++
 include/net/cfg80211.h    |   28 ++++++++++
 net/wireless/nl80211.c    |  120 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 161 insertions(+), 0 deletions(-)
include/linux/ieee80211.h +2 -0
index afa8e0a..d9724a2 100644
@@ -1266,6 +1266,8 @@ enum ieee80211_sa_query_action {
 
 #define WLAN_MAX_KEY_LEN		32
 
+#define WLAN_PMKID_LEN			16
+
 /**
  * ieee80211_get_qos_ctl - get pointer to qos control bytes
  * @hdr: the frame
include/linux/nl80211.h +11 -0
index 45db17f..da8ea2e 100644
@@ -349,6 +349,10 @@ enum nl80211_commands {
 	NL80211_CMD_GET_SURVEY,
 	NL80211_CMD_NEW_SURVEY_RESULTS,
 
+	NL80211_CMD_SET_PMKSA,
+	NL80211_CMD_DEL_PMKSA,
+	NL80211_CMD_FLUSH_PMKSA,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -598,6 +602,10 @@ enum nl80211_commands {
  *      the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
  *      containing info as possible, see &enum survey_info.
  *
+ * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
+ * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
+ *	cache, a wiphy attribute.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -732,6 +740,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_SURVEY_INFO,
 
+	NL80211_ATTR_PMKID,
+	NL80211_ATTR_MAX_NUM_PMKIDS,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
include/net/cfg80211.h +28 -0
index a6492e9..0884b9a 100644
@@ -871,6 +871,19 @@ struct cfg80211_bitrate_mask {
 	u32 fixed;   /* fixed bitrate, 0 == not fixed */
 	u32 maxrate; /* in kbps, 0 == no limit */
 };
+/**
+ * struct cfg80211_pmksa - PMK Security Association
+ *
+ * This structure is passed to the set/del_pmksa() method for PMKSA
+ * caching.
+ *
+ * @bssid: The AP's BSSID.
+ * @pmkid: The PMK material itself.
+ */
+struct cfg80211_pmksa {
+	u8 *bssid;
+	u8 *pmkid;
+};
 
 /**
  * struct cfg80211_ops - backend description for wireless configuration
@@ -976,6 +989,13 @@ struct cfg80211_bitrate_mask {
  * @dump_survey: get site survey information.
  *
  * @testmode_cmd: run a test mode command
+ *
+ * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
+ *	devices running firmwares capable of generating the (re) association
+ *	RSN IE. It allows for faster roaming between WPA2 BSSIDs.
+ * @del_pmksa: Delete a cached PMKID.
+ * @flush_pmksa: Flush all cached PMKIDs.
+ *
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -1097,6 +1117,12 @@ struct cfg80211_ops {
 	int	(*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
 			int idx, struct survey_info *info);
 
+	int	(*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+			     struct cfg80211_pmksa *pmksa);
+	int	(*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
+			     struct cfg80211_pmksa *pmksa);
+	int	(*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
+
 	/* some temporary stuff to finish wext */
 	int	(*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
 				  bool enabled, int timeout);
@@ -1195,6 +1221,8 @@ struct wiphy {
 	char fw_version[ETHTOOL_BUSINFO_LEN];
 	u32 hw_version;
 
+	u8 max_num_pmkids;
+
 	/* If multiple wiphys are registered and you're handed e.g.
 	 * a regular netdev with assigned ieee80211_ptr, you won't
 	 * know whether it points to a wiphy your driver has registered
net/wireless/nl80211.c +120 -0

150 lines not on this page · raw message

Signature · 5 lines
1.6.3.3

-- 
Intel Open Source Technology Centre
http://oss.intel.com/