All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols
@ 2010-08-27 11:07 Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 1/4] cfg80211: allow vendor specific cipher suites Juuso Oikarinen
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:07 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, johannes.berg

These patches enable usage of hw-only cipher-suites, and enable using
control port ethertypes other than ETH_P_PAE for key-negotiation.

These patches are originally written by Johannes Berg, finalized and tested by
myself.

Johannes Berg (4):
  cfg80211: allow vendor specific cipher suites
  mac80211: allow vendor specific cipher suites
  cfg80211: allow changing port control protocol
  mac80211: allow changing port control protocol

 include/linux/nl80211.h    |   16 ++++++++++++++-
 include/net/cfg80211.h     |   24 +++++++++++++++------
 net/mac80211/cfg.c         |    5 ++-
 net/mac80211/ieee80211_i.h |    4 +++
 net/mac80211/iface.c       |    2 +
 net/mac80211/key.c         |   38 ++++++++++++++++++++++++++++-------
 net/mac80211/key.h         |    6 ++--
 net/mac80211/main.c        |   47 ++++++++++++++++++++++++++++++++++++++-----
 net/mac80211/mlme.c        |    3 ++
 net/mac80211/rx.c          |    8 ++++++-
 net/mac80211/tx.c          |   32 +++++++++++++++++++++++++----
 net/wireless/nl80211.c     |   25 ++++++++++++++++++++--
 net/wireless/util.c        |    9 +++++++-
 net/wireless/wext-sme.c    |    2 +
 14 files changed, 184 insertions(+), 37 deletions(-)


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] cfg80211: allow vendor specific cipher suites
  2010-08-27 11:07 [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols Juuso Oikarinen
@ 2010-08-27 11:07 ` Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 2/4] mac80211: " Juuso Oikarinen
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:07 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, johannes.berg

From: Johannes Berg <johannes.berg@intel.com>

cfg80211 currently rejects all cipher suites it
doesn't know about for key length checking
purposes. This can lead to inconsistencies when
a driver advertises an algorithm that cfg80211
doesn't know about. Remove this rejection so
drivers can specify any algorithm they like.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 net/wireless/util.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index 8d961cc..bca32eb 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -183,7 +183,14 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 			return -EINVAL;
 		break;
 	default:
-		return -EINVAL;
+		/*
+		 * We don't know anything about this algorithm,
+		 * allow using it -- but the driver must check
+		 * all parameters! We still check below whether
+		 * or not the driver supports this algorithm,
+		 * of course.
+		 */
+		break;
 	}
 
 	if (params->seq) {
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] mac80211: allow vendor specific cipher suites
  2010-08-27 11:07 [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 1/4] cfg80211: allow vendor specific cipher suites Juuso Oikarinen
@ 2010-08-27 11:07 ` Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 3/4] cfg80211: allow changing port control protocol Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 4/4] mac80211: " Juuso Oikarinen
  3 siblings, 0 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:07 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, johannes.berg

From: Johannes Berg <johannes.berg@intel.com>

Allow drivers to specify their own set of cipher
suites to advertise vendor-specific ciphers. The
driver is then required to implement hardware
crypto offload for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 net/mac80211/cfg.c         |    5 +++--
 net/mac80211/ieee80211_i.h |    2 ++
 net/mac80211/key.c         |   38 ++++++++++++++++++++++++++++++--------
 net/mac80211/key.h         |    6 +++---
 net/mac80211/main.c        |   44 ++++++++++++++++++++++++++++++++++++++------
 net/mac80211/rx.c          |    6 ++++++
 net/mac80211/tx.c          |   12 ++++++++++--
 7 files changed, 92 insertions(+), 21 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5814382..f149b4e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -119,9 +119,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 		}
 	}
 
-	ieee80211_key_link(key, sdata, sta);
+	err = ieee80211_key_link(key, sdata, sta);
+	if (err)
+		ieee80211_key_free(sdata->local, key);
 
-	err = 0;
  out_unlock:
 	mutex_unlock(&sdata->local->sta_mtx);
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e73ae51..0262dfe 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -662,6 +662,8 @@ struct ieee80211_local {
 	int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll;
 	unsigned int filter_flags; /* FIF_* */
 
+	bool wiphy_ciphers_allocated;
+
 	/* protects the aggregated multicast list and filter calls */
 	spinlock_t filter_lock;
 
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 2ce2dbb..3570f8c 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -60,7 +60,7 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
 	return NULL;
 }
 
-static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
+static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_sta *sta;
@@ -68,8 +68,10 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 
 	might_sleep();
 
-	if (!key->local->ops->set_key)
-		return;
+	if (!key->local->ops->set_key) {
+		ret = -EOPNOTSUPP;
+		goto out_unsupported;
+	}
 
 	assert_key_lock(key->local);
 
@@ -90,6 +92,24 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
 		wiphy_err(key->local->hw.wiphy,
 			  "failed to set key (%d, %pM) to hardware (%d)\n",
 			  key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+
+out_unsupported:
+	if (ret) {
+		switch (key->conf.cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+		case WLAN_CIPHER_SUITE_TKIP:
+		case WLAN_CIPHER_SUITE_CCMP:
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			/* all of these we can do in software */
+			ret = 0;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
 }
 
 static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
@@ -329,12 +349,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
 	kfree(key);
 }
 
-void ieee80211_key_link(struct ieee80211_key *key,
-			struct ieee80211_sub_if_data *sdata,
-			struct sta_info *sta)
+int ieee80211_key_link(struct ieee80211_key *key,
+		       struct ieee80211_sub_if_data *sdata,
+		       struct sta_info *sta)
 {
 	struct ieee80211_key *old_key;
-	int idx;
+	int idx, ret;
 
 	BUG_ON(!sdata);
 	BUG_ON(!key);
@@ -389,9 +409,11 @@ void ieee80211_key_link(struct ieee80211_key *key,
 
 	ieee80211_debugfs_key_add(key);
 
-	ieee80211_key_enable_hw_accel(key);
+	ret = ieee80211_key_enable_hw_accel(key);
 
 	mutex_unlock(&sdata->local->key_mtx);
+
+	return ret;
 }
 
 static void __ieee80211_key_free(struct ieee80211_key *key)
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 53b5ce1..cb9a4a6 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -130,9 +130,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
  * Insert a key into data structures (sdata, sta if necessary)
  * to make it used, free old key.
  */
-void ieee80211_key_link(struct ieee80211_key *key,
-			struct ieee80211_sub_if_data *sdata,
-			struct sta_info *sta);
+int __must_check ieee80211_key_link(struct ieee80211_key *key,
+				    struct ieee80211_sub_if_data *sdata,
+				    struct sta_info *sta);
 void ieee80211_key_free(struct ieee80211_local *local,
 			struct ieee80211_key *key);
 void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 80db5ea..15f0e96 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -662,13 +662,40 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (local->hw.wiphy->max_scan_ie_len)
 		local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
 
-	local->hw.wiphy->cipher_suites = cipher_suites;
-	local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
-	if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
-		local->hw.wiphy->n_cipher_suites--;
+	/* Set up cipher suites unless driver already did */
+	if (!local->hw.wiphy->cipher_suites) {
+		local->hw.wiphy->cipher_suites = cipher_suites;
+		local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+		if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
+			local->hw.wiphy->n_cipher_suites--;
+	}
 	if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
-		local->hw.wiphy->cipher_suites += 2;
-		local->hw.wiphy->n_cipher_suites -= 2;
+		if (local->hw.wiphy->cipher_suites == cipher_suites) {
+			local->hw.wiphy->cipher_suites += 2;
+			local->hw.wiphy->n_cipher_suites -= 2;
+		} else {
+			u32 *suites;
+			int r, w = 0;
+
+			/* Filter out WEP */
+
+			suites = kmemdup(
+				local->hw.wiphy->cipher_suites,
+				sizeof(u32) * local->hw.wiphy->n_cipher_suites,
+				GFP_KERNEL);
+			if (!suites)
+				return -ENOMEM;
+			for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
+				u32 suite = local->hw.wiphy->cipher_suites[r];
+				if (suite == WLAN_CIPHER_SUITE_WEP40 ||
+				    suite == WLAN_CIPHER_SUITE_WEP104)
+					continue;
+				suites[w++] = suite;
+			}
+			local->hw.wiphy->cipher_suites = suites;
+			local->hw.wiphy->n_cipher_suites = w;
+			local->wiphy_ciphers_allocated = true;
+		}
 	}
 
 	result = wiphy_register(local->hw.wiphy);
@@ -783,6 +810,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
  fail_workqueue:
 	wiphy_unregister(local->hw.wiphy);
  fail_wiphy_register:
+	if (local->wiphy_ciphers_allocated)
+		kfree(local->hw.wiphy->cipher_suites);
 	kfree(local->int_scan_req);
 	return result;
 }
@@ -840,6 +869,9 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
 	mutex_destroy(&local->iflist_mtx);
 	mutex_destroy(&local->mtx);
 
+	if (local->wiphy_ciphers_allocated)
+		kfree(local->hw.wiphy->cipher_suites);
+
 	wiphy_free(local->hw.wiphy);
 }
 EXPORT_SYMBOL(ieee80211_free_hw);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e67deb4..6e5fb16 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1000,6 +1000,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
 	case WLAN_CIPHER_SUITE_AES_CMAC:
 		result = ieee80211_crypto_aes_cmac_decrypt(rx);
 		break;
+	default:
+		/*
+		 * We can reach here only with HW-only algorithms
+		 * but why didn't it decrypt the frame?!
+		 */
+		return RX_DROP_UNUSABLE;
 	}
 
 	/* either the frame has been decrypted or will be dropped */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index a6ac9fd..31a8903 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -947,6 +947,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
 {
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
 	if (!tx->key)
 		return TX_CONTINUE;
 
@@ -960,10 +962,16 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
 		return ieee80211_crypto_ccmp_encrypt(tx);
 	case WLAN_CIPHER_SUITE_AES_CMAC:
 		return ieee80211_crypto_aes_cmac_encrypt(tx);
+	default:
+		/* handle hw-only algorithm */
+		if (info->control.hw_key) {
+			ieee80211_tx_set_protected(tx);
+			return TX_CONTINUE;
+		}
+		break;
+
 	}
 
-	/* not reached */
-	WARN_ON(1);
 	return TX_DROP;
 }
 
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] cfg80211: allow changing port control protocol
  2010-08-27 11:07 [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 1/4] cfg80211: allow vendor specific cipher suites Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 2/4] mac80211: " Juuso Oikarinen
@ 2010-08-27 11:07 ` Juuso Oikarinen
  2010-08-27 11:07 ` [PATCH 4/4] mac80211: " Juuso Oikarinen
  3 siblings, 0 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:07 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, johannes.berg

From: Johannes Berg <johannes.berg@intel.com>

Some vendor specified mechanisms for 802.1X-style
functionality use a different protocol than EAP
(even if EAP is vendor-extensible). Allow setting
the ethertype for the protocol when a driver has
support for this. The default if unspecified is
EAP, of course.

Note: This is suitable only for station mode, not
      for AP implementation.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 include/linux/nl80211.h |   16 +++++++++++++++-
 include/net/cfg80211.h  |   24 +++++++++++++++++-------
 net/wireless/nl80211.c  |   25 ++++++++++++++++++++++---
 net/wireless/wext-sme.c |    2 ++
 4 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index ec1690d..31603e8 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -295,7 +295,9 @@
  *	auth and assoc steps. For this, you need to specify the SSID in a
  *	%NL80211_ATTR_SSID attribute, and can optionally specify the association
  *	IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC,
- *	%NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT.
+ *	%NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT,
+ *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE and
+ *	%NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT.
  *	It is also sent as an event, with the BSSID and response IEs when the
  *	connection is established or failed to be established. This can be
  *	determined by the STATUS_CODE attribute.
@@ -686,6 +688,15 @@ enum nl80211_commands {
  *	request, the driver will assume that the port is unauthorized until
  *	authorized by user space. Otherwise, port is marked authorized by
  *	default in station mode.
+ * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the
+ *	ethertype that will be used for key negotiation. It can be
+ *	specified with the associate and connect commands. If it is not
+ *	specified, the value defaults to 0x888E (PAE, 802.1X). This
+ *	attribute is also used as a flag in the wiphy information to
+ *	indicate that protocols other than PAE are supported.
+ * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with
+ *	%NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom
+ *	ethertype frames used for key negotiation must not be encrypted.
  *
  * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
  *	We recommend using nested, driver-specific attributes within this.
@@ -951,6 +962,9 @@ enum nl80211_attrs {
 	NL80211_ATTR_RX_FRAME_TYPES,
 	NL80211_ATTR_FRAME_TYPE,
 
+	NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
+	NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f274053..4c8c727 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -763,6 +763,10 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
  *	sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
  *	required to assume that the port is unauthorized until authorized by
  *	user space. Otherwise, port is marked authorized by default.
+ * @control_port_ethertype: the control port protocol that should be
+ *	allowed through even on unauthorized ports
+ * @control_port_no_encrypt: TRUE to prevent encryption of control port
+ *	protocol frames.
  */
 struct cfg80211_crypto_settings {
 	u32 wpa_versions;
@@ -772,6 +776,8 @@ struct cfg80211_crypto_settings {
 	int n_akm_suites;
 	u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
 	bool control_port;
+	__be16 control_port_ethertype;
+	bool control_port_no_encrypt;
 };
 
 /**
@@ -1293,15 +1299,19 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station
  *	on a VLAN interface)
  * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station
+ * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the
+ *	control port protocol ethertype. The device also honours the
+ *	control_port_no_encrypt flag.
  */
 enum wiphy_flags {
-	WIPHY_FLAG_CUSTOM_REGULATORY	= BIT(0),
-	WIPHY_FLAG_STRICT_REGULATORY	= BIT(1),
-	WIPHY_FLAG_DISABLE_BEACON_HINTS	= BIT(2),
-	WIPHY_FLAG_NETNS_OK		= BIT(3),
-	WIPHY_FLAG_PS_ON_BY_DEFAULT	= BIT(4),
-	WIPHY_FLAG_4ADDR_AP		= BIT(5),
-	WIPHY_FLAG_4ADDR_STATION	= BIT(6),
+	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
+	WIPHY_FLAG_STRICT_REGULATORY		= BIT(1),
+	WIPHY_FLAG_DISABLE_BEACON_HINTS		= BIT(2),
+	WIPHY_FLAG_NETNS_OK			= BIT(3),
+	WIPHY_FLAG_PS_ON_BY_DEFAULT		= BIT(4),
+	WIPHY_FLAG_4ADDR_AP			= BIT(5),
+	WIPHY_FLAG_4ADDR_STATION		= BIT(6),
+	WIPHY_FLAG_CONTROL_PORT_PROTOCOL	= BIT(7),
 };
 
 struct mac_address {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 49f5ca3..85a23de 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -136,6 +136,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 		.len = sizeof(struct nl80211_sta_flag_update),
 	},
 	[NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_CONTROL_PORT_ETHERTYPE] = { .type = NLA_U16 },
+	[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_PRIVACY] = { .type = NLA_FLAG },
 	[NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
 	[NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
@@ -474,6 +476,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 	NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
 		   dev->wiphy.max_num_pmkids);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE);
+
 	nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
 	if (!nl_modes)
 		goto nla_put_failure;
@@ -3691,7 +3696,8 @@ unlock_rtnl:
 	return err;
 }
 
-static int nl80211_crypto_settings(struct genl_info *info,
+static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
+				   struct genl_info *info,
 				   struct cfg80211_crypto_settings *settings,
 				   int cipher_limit)
 {
@@ -3699,6 +3705,19 @@ static int nl80211_crypto_settings(struct genl_info *info,
 
 	settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
 
+	if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
+		u16 proto;
+		proto = nla_get_u16(
+			info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
+		settings->control_port_ethertype = cpu_to_be16(proto);
+		if (!(rdev->wiphy.flags & WIPHY_FLAG_CONTROL_PORT_PROTOCOL) &&
+		    proto != ETH_P_PAE)
+			return -EINVAL;
+		if (info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT])
+			settings->control_port_no_encrypt = true;
+	} else
+		settings->control_port_ethertype = cpu_to_be16(ETH_P_PAE);
+
 	if (info->attrs[NL80211_ATTR_CIPHER_SUITES_PAIRWISE]) {
 		void *data;
 		int len, i;
@@ -3826,7 +3845,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 	if (info->attrs[NL80211_ATTR_PREV_BSSID])
 		prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
-	err = nl80211_crypto_settings(info, &crypto, 1);
+	err = nl80211_crypto_settings(rdev, info, &crypto, 1);
 	if (!err)
 		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
 					  ssid, ssid_len, ie, ie_len, use_mfp,
@@ -4303,7 +4322,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 
 	connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
 
-	err = nl80211_crypto_settings(info, &connect.crypto,
+	err = nl80211_crypto_settings(rdev, info, &connect.crypto,
 				      NL80211_MAX_NR_CIPHER_SUITES);
 	if (err)
 		return err;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 9818198..6fffe62 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -197,6 +197,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
 	wdev->wext.connect.ssid_len = len;
 
 	wdev->wext.connect.crypto.control_port = false;
+	wdev->wext.connect.crypto.control_port_ethertype =
+					cpu_to_be16(ETH_P_PAE);
 
 	err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] mac80211: allow changing port control protocol
  2010-08-27 11:07 [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols Juuso Oikarinen
                   ` (2 preceding siblings ...)
  2010-08-27 11:07 ` [PATCH 3/4] cfg80211: allow changing port control protocol Juuso Oikarinen
@ 2010-08-27 11:07 ` Juuso Oikarinen
  2010-08-27 11:13   ` Johannes Berg
  3 siblings, 1 reply; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:07 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, johannes.berg

From: Johannes Berg <johannes.berg@intel.com>

Some vendor specified mechanisms for 802.1X-style
functionality use a different protocol than EAP
(even if EAP is vendor-extensible). Support this
in mac80211 via the cfg80211 API for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 net/mac80211/ieee80211_i.h |    2 ++
 net/mac80211/iface.c       |    2 ++
 net/mac80211/main.c        |    3 +++
 net/mac80211/mlme.c        |    3 +++
 net/mac80211/rx.c          |    2 +-
 net/mac80211/tx.c          |   20 +++++++++++++++++---
 6 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0262dfe..d7e7989 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -515,6 +515,8 @@ struct ieee80211_sub_if_data {
 	struct ieee80211_key *default_mgmt_key;
 
 	u16 sequence_number;
+	__be16 control_port_protocol;
+	bool control_port_no_encrypt;
 
 	struct work_struct work;
 	struct sk_buff_head skb_queue;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9369710..ba2ce55 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -855,6 +855,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
 	sdata->wdev.iftype = type;
 
+	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
+
 	/* only monitor differs */
 	sdata->dev->type = ARPHRD_ETHER;
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 15f0e96..964c267 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -627,6 +627,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
 #endif
 
+	/* mac80211 supports control port protocol changing */
+	local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
+
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
 		local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5282ac1..0cb4296 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2262,6 +2262,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	else
 		ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
 
+	sdata->control_port_protocol = req->crypto.control_port_ethertype;
+	sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
+
 	ieee80211_add_work(wk);
 	return 0;
 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6e5fb16..ac205a3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1527,7 +1527,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
 	 * Allow EAPOL frames to us/the PAE group address regardless
 	 * of whether the frame was encrypted or not.
 	 */
-	if (ehdr->h_proto == htons(ETH_P_PAE) &&
+	if (ehdr->h_proto == rx->sdata->control_port_protocol &&
 	    (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 ||
 	     compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
 		return true;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 31a8903..92764bb 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -509,6 +509,18 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
 }
 
 static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+
+	if (unlikely(tx->sdata->control_port_protocol == tx->skb->protocol &&
+		     tx->sdata->control_port_no_encrypt))
+		info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+	return TX_CONTINUE;
+}
+
+static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
 	struct ieee80211_key *key = NULL;
@@ -527,7 +539,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 	else if ((key = rcu_dereference(tx->sdata->default_key)))
 		tx->key = key;
 	else if (tx->sdata->drop_unencrypted &&
-		 (tx->skb->protocol != cpu_to_be16(ETH_P_PAE)) &&
+		 (tx->skb->protocol != tx->sdata->control_port_protocol) &&
 		 !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
 		 (!ieee80211_is_robust_mgmt_frame(hdr) ||
 		  (ieee80211_is_action(hdr->frame_control) &&
@@ -1349,6 +1361,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 	CALL_TXH(ieee80211_tx_h_dynamic_ps);
 	CALL_TXH(ieee80211_tx_h_check_assoc);
 	CALL_TXH(ieee80211_tx_h_ps_buf);
+	CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
 	CALL_TXH(ieee80211_tx_h_select_key);
 	if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
 		CALL_TXH(ieee80211_tx_h_rate_ctrl);
@@ -1826,7 +1839,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 #endif
 	case NL80211_IFTYPE_STATION:
 		memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
-		if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) {
+		if (sdata->u.mgd.use_4addr &&
+		    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
 			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
 			/* RA TA DA SA */
 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
@@ -1879,7 +1893,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
 		unlikely(!is_multicast_ether_addr(hdr.addr1) &&
 		      !(sta_flags & WLAN_STA_AUTHORIZED) &&
-		      !(ethertype == ETH_P_PAE &&
+		      !(cpu_to_be16(ethertype) == sdata->control_port_protocol &&
 		       compare_ether_addr(sdata->vif.addr,
 					  skb->data + ETH_ALEN) == 0))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] mac80211: allow changing port control protocol
  2010-08-27 11:07 ` [PATCH 4/4] mac80211: " Juuso Oikarinen
@ 2010-08-27 11:13   ` Johannes Berg
  2010-08-27 11:18     ` Juuso Oikarinen
  0 siblings, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2010-08-27 11:13 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linville, linux-wireless

On Fri, 2010-08-27 at 14:07 +0300, Juuso Oikarinen wrote:

> @@ -855,6 +855,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
>  	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
>  	sdata->wdev.iftype = type;
>  
> +	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
> +

I believe we may also need to set control_port_no_encrypt to false here,
or we'll run into issues with interface type switching after it had been
true?

johannes


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] mac80211: allow changing port control protocol
  2010-08-27 11:13   ` Johannes Berg
@ 2010-08-27 11:18     ` Juuso Oikarinen
  0 siblings, 0 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2010-08-27 11:18 UTC (permalink / raw)
  To: ext Johannes Berg; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org

On Fri, 2010-08-27 at 13:13 +0200, ext Johannes Berg wrote:
> On Fri, 2010-08-27 at 14:07 +0300, Juuso Oikarinen wrote:
> 
> > @@ -855,6 +855,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
> >  	sdata->dev->netdev_ops = &ieee80211_dataif_ops;
> >  	sdata->wdev.iftype = type;
> >  
> > +	sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE);
> > +
> 
> I believe we may also need to set control_port_no_encrypt to false here,
> or we'll run into issues with interface type switching after it had been
> true?

Sounds valid. I'll send v2 still.

-Juuso

> johannes
> 



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-08-27 11:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-08-27 11:07 [PATCH 0/4] mac80211: cfg80211: support for hw-only crypts and custom control port protocols Juuso Oikarinen
2010-08-27 11:07 ` [PATCH 1/4] cfg80211: allow vendor specific cipher suites Juuso Oikarinen
2010-08-27 11:07 ` [PATCH 2/4] mac80211: " Juuso Oikarinen
2010-08-27 11:07 ` [PATCH 3/4] cfg80211: allow changing port control protocol Juuso Oikarinen
2010-08-27 11:07 ` [PATCH 4/4] mac80211: " Juuso Oikarinen
2010-08-27 11:13   ` Johannes Berg
2010-08-27 11:18     ` Juuso Oikarinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.