From 484a54c2e597dbc4ace79c1687022282905afba0 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 6 Apr 2017 11:38:26 +0200 Subject: mac80211: Dynamically set CoDel parameters per station MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CoDel can be too aggressive if a station sends at a very low rate, leading reduced throughput. This gets worse the more stations are present, as each station gets more bursty the longer the round-robin scheduling between stations takes. This adds dynamic adjustment of CoDel parameters per station. It uses the rate selection information to estimate throughput and sets more lenient CoDel parameters if the estimated throughput is below a threshold (modified by the number of active stations). A new callback is added that drivers can use to notify mac80211 about changes in expected throughput, so the same adjustment can be made for cards that implement rate control in firmware. Drivers that don't use this will just get the default parameters. Signed-off-by: Toke Høiland-Jørgensen [remove currently unnecessary EXPORT_SYMBOL, fix kernel-doc, remove inline annotation] Signed-off-by: Johannes Berg --- include/net/mac80211.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include/net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 76ed24a201eb..e01daff1e255 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -4204,6 +4204,22 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, struct ieee80211_tx_rate *dest, int max_rates); +/** + * ieee80211_sta_set_expected_throughput - set the expected tpt for a station + * + * Call this function to notify mac80211 about a change in expected throughput + * to a station. A driver for a device that does rate control in firmware can + * call this function when the expected throughput estimate towards a station + * changes. The information is used to tune the CoDel AQM applied to traffic + * going towards that station (which can otherwise be too aggressive and cause + * slow stations to starve). + * + * @pubsta: the station to set throughput for. + * @thr: the current expected throughput in kbps. + */ +void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta, + u32 thr); + /** * ieee80211_tx_status - transmit status callback * -- cgit v1.2.3 From d37d49c2f18fb53c6315b2b0fd7f1fb3d8be57ac Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 16 May 2017 11:23:11 +0200 Subject: wireless: Only join DFS channels in mesh mode if userspace flags support When joining a mesh network it is not guaranteed that userspace has a daemon listening for radar events. This is however required for channels requiring DFS. To flag that userspace will handle radar events, it needs to set NL80211_ATTR_HANDLE_DFS. This matches the current mechanism used for IBSS mode. Signed-off-by: Benjamin Berg Signed-off-by: Simon Wunderlich Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++++ net/wireless/mesh.c | 8 ++++++++ net/wireless/nl80211.c | 3 +++ 3 files changed, 15 insertions(+) (limited to 'include/net') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b083e6cbae8c..fa25fbb67cb6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1441,6 +1441,9 @@ struct mesh_config { * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] * @basic_rates: basic rates to use when creating the mesh * @beacon_rate: bitrate to be used for beacons + * @userspace_handles_dfs: whether user space controls DFS operation, i.e. + * changes the channel when a radar is detected. This is required + * to operate on DFS channels. * * These parameters are fixed when the mesh is created. */ @@ -1462,6 +1465,7 @@ struct mesh_setup { int mcast_rate[NUM_NL80211_BANDS]; u32 basic_rates; struct cfg80211_bitrate_mask beacon_rate; + bool userspace_handles_dfs; }; /** diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index ec0b1c20ac99..421a6b80ec62 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -174,6 +174,14 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, scan_width); } + err = cfg80211_chandef_dfs_required(&rdev->wiphy, + &setup->chandef, + NL80211_IFTYPE_MESH_POINT); + if (err < 0) + return err; + if (err > 0 && !setup->userspace_handles_dfs) + return -EINVAL; + if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef, NL80211_IFTYPE_MESH_POINT)) return -EINVAL; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c3bc9da30cff..d47e55e3f445 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9962,6 +9962,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) return err; } + setup.userspace_handles_dfs = + nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]); + return cfg80211_join_mesh(rdev, dev, &setup, &cfg); } -- cgit v1.2.3 From 699cb58c8a52ff39bf659bff7971893ebe111bf2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 May 2017 16:34:46 +0200 Subject: mac80211: manage RX BA session offload without SKB queue Instead of using the SKB queue with the fake pkt_type for the offloaded RX BA session management, also handle this with the normal aggregation state machine worker. This also makes the use of this more reliable since it gets rid of the allocation of the fake skb. Combined with the previous patch, this finally allows us to get rid of the pkt_type hack entirely, so do that as well. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 21 +++++++++++++++++---- net/mac80211/agg-rx.c | 47 ++++++++++++---------------------------------- net/mac80211/ht.c | 12 ++++++++++++ net/mac80211/ieee80211_i.h | 11 ----------- net/mac80211/iface.c | 25 ++---------------------- net/mac80211/rx.c | 4 ---- net/mac80211/sta_info.h | 3 +++ 7 files changed, 46 insertions(+), 77 deletions(-) (limited to 'include/net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e01daff1e255..b2b5419467cc 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5452,6 +5452,9 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid, */ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); +void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr, + unsigned int bit); + /** * ieee80211_start_rx_ba_session_offl - start a Rx BA session * @@ -5466,8 +5469,13 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); * @addr: station mac address * @tid: the rx tid */ -void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, - const u8 *addr, u16 tid); +static inline void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, + const u8 *addr, u16 tid) +{ + if (WARN_ON(tid >= IEEE80211_NUM_TIDS)) + return; + ieee80211_manage_rx_ba_offl(vif, addr, tid); +} /** * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session @@ -5483,8 +5491,13 @@ void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, * @addr: station mac address * @tid: the rx tid */ -void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, - const u8 *addr, u16 tid); +static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, + const u8 *addr, u16 tid) +{ + if (WARN_ON(tid >= IEEE80211_NUM_TIDS)) + return; + ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS); +} /* Rate control API */ diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 1b7a4daf283c..3a0282188ad6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -449,44 +449,21 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, buf_size, true, false); } -void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, - const u8 *addr, u16 tid) +void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, + const u8 *addr, unsigned int bit) { struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); struct ieee80211_local *local = sdata->local; - struct ieee80211_rx_agg *rx_agg; - struct sk_buff *skb = dev_alloc_skb(0); - - if (unlikely(!skb)) - return; - - rx_agg = (struct ieee80211_rx_agg *) &skb->cb; - memcpy(&rx_agg->addr, addr, ETH_ALEN); - rx_agg->tid = tid; - - skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START; - skb_queue_tail(&sdata->skb_queue, skb); - ieee80211_queue_work(&local->hw, &sdata->work); -} -EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl); - -void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, - const u8 *addr, u16 tid) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - struct ieee80211_local *local = sdata->local; - struct ieee80211_rx_agg *rx_agg; - struct sk_buff *skb = dev_alloc_skb(0); - - if (unlikely(!skb)) - return; + struct sta_info *sta; - rx_agg = (struct ieee80211_rx_agg *) &skb->cb; - memcpy(&rx_agg->addr, addr, ETH_ALEN); - rx_agg->tid = tid; + rcu_read_lock(); + sta = sta_info_get_bss(sdata, addr); + if (!sta) + goto unlock; - skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP; - skb_queue_tail(&sdata->skb_queue, skb); - ieee80211_queue_work(&local->hw, &sdata->work); + set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl); + ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); + unlock: + rcu_read_unlock(); } -EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl); +EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 6ca5442b1e03..9e71226c2d25 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -331,6 +331,18 @@ void ieee80211_ba_session_work(struct work_struct *work) sta, tid, WLAN_BACK_RECIPIENT, WLAN_REASON_UNSPECIFIED, true); + if (test_and_clear_bit(tid, + sta->ampdu_mlme.tid_rx_manage_offl)) + __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid, + IEEE80211_MAX_AMPDU_BUF, + false, true); + + if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS, + sta->ampdu_mlme.tid_rx_manage_offl)) + ___ieee80211_stop_rx_ba_session( + sta, tid, WLAN_BACK_RECIPIENT, + 0, false); + spin_lock_bh(&sta->lock); tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f24f1d7b8937..392fbab73c04 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1031,17 +1031,6 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif) return shift; } -struct ieee80211_rx_agg { - u8 addr[ETH_ALEN]; - u16 tid; -}; - -enum sdata_queue_type { - IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, - IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, - IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, -}; - enum { IEEE80211_RX_MSG = 1, IEEE80211_TX_STATUS_MSG = 2, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8fae1a72e6a7..6ac0a0198d19 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work) struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct sta_info *sta; - struct ieee80211_rx_agg *rx_agg; if (!ieee80211_sdata_running(sdata)) return; @@ -1252,28 +1251,8 @@ static void ieee80211_iface_work(struct work_struct *work) while ((skb = skb_dequeue(&sdata->skb_queue))) { struct ieee80211_mgmt *mgmt = (void *)skb->data; - if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { - rx_agg = (void *)&skb->cb; - mutex_lock(&local->sta_mtx); - sta = sta_info_get_bss(sdata, rx_agg->addr); - if (sta) - __ieee80211_start_rx_ba_session(sta, - 0, 0, 0, 1, rx_agg->tid, - IEEE80211_MAX_AMPDU_BUF, - false, true); - mutex_unlock(&local->sta_mtx); - } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) { - rx_agg = (void *)&skb->cb; - mutex_lock(&local->sta_mtx); - sta = sta_info_get_bss(sdata, rx_agg->addr); - if (sta) - __ieee80211_stop_rx_ba_session(sta, - rx_agg->tid, - WLAN_BACK_RECIPIENT, 0, - false); - mutex_unlock(&local->sta_mtx); - } else if (ieee80211_is_action(mgmt->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_BACK) { + if (ieee80211_is_action(mgmt->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_BACK) { int len = skb->len; mutex_lock(&local->sta_mtx); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1f75280ba26c..8c7d932fd09b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -237,7 +237,6 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata, if (!skb) return; - skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; skb_queue_tail(&sdata->skb_queue, skb); ieee80211_queue_work(&sdata->local->hw, &sdata->work); } @@ -1217,7 +1216,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, /* if this mpdu is fragmented - terminate rx aggregation session */ sc = le16_to_cpu(hdr->seq_ctrl); if (sc & IEEE80211_SCTL_FRAG) { - skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; skb_queue_tail(&rx->sdata->skb_queue, skb); ieee80211_queue_work(&local->hw, &rx->sdata->work); return; @@ -3100,7 +3098,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) return RX_QUEUED; queue: - rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; skb_queue_tail(&sdata->skb_queue, rx->skb); ieee80211_queue_work(&local->hw, &sdata->work); if (rx->sta) @@ -3246,7 +3243,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) } /* queue up frame and kick off work to process it */ - rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; skb_queue_tail(&sdata->skb_queue, rx->skb); ieee80211_queue_work(&rx->local->hw, &sdata->work); if (rx->sta) diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index cde89c6d0386..3acbdfa9f649 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -233,6 +233,8 @@ struct tid_ampdu_rx { * RX timer expired until the work for it runs * @tid_rx_stop_requested: bitmap indicating which BA sessions per TID the * driver requested to close until the work for it runs + * @tid_rx_manage_offl: bitmap indicating which BA sessions were requested + * to be treated as started/stopped due to offloading * @agg_session_valid: bitmap indicating which TID has a rx BA session open on * @unexpected_agg: bitmap indicating which TID already sent a delBA due to * unexpected aggregation related frames outside a session @@ -250,6 +252,7 @@ struct sta_ampdu_mlme { u8 tid_rx_token[IEEE80211_NUM_TIDS]; unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; + unsigned long tid_rx_manage_offl[BITS_TO_LONGS(2 * IEEE80211_NUM_TIDS)]; unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; unsigned long unexpected_agg[BITS_TO_LONGS(IEEE80211_NUM_TIDS)]; /* tx */ -- cgit v1.2.3 From 91b5ab628929d97357108594610e7c07be93e2fd Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 9 Jun 2017 13:08:42 +0100 Subject: cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK Let drivers advertise support for station-mode 4-way handshake offloading with a new NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag. Extend use of NL80211_ATTR_PMK attribute indicating it might be passed as part of NL80211_CMD_CONNECT command, and contain the PSK (which is the PMK, hence the name.) The driver/device is assumed to handle the 4-way handshake by itself in this case (including key derivations, etc.), instead of relying on the supplicant. This patch is somewhat based on this one (by Vladimir Kondratiev): https://patchwork.kernel.org/patch/1309561/. Signed-off-by: Vladimir Kondratiev Signed-off-by: Eliad Peller Signed-off-by: Luca Coelho [arend.vanspriel@broadcom.com rebase dealing with existing ATTR_PMK] Signed-off-by: Arend van Spriel [reword NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK docs to indicate that this offload might be required] Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 1 + include/net/cfg80211.h | 2 ++ include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++-- net/wireless/nl80211.c | 9 +++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) (limited to 'include/net') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 69033353d0d1..e97ca3a9a67b 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2401,6 +2401,7 @@ enum ieee80211_sa_query_action { #define WLAN_MAX_KEY_LEN 32 #define WLAN_PMKID_LEN 16 +#define WLAN_PMK_LEN 32 #define WLAN_OUI_WFA 0x506f9a #define WLAN_OUI_TYPE_WFA_P2P 9 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fa25fbb67cb6..1b288bac5d1a 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -649,6 +649,7 @@ struct survey_info { * @wep_keys: static WEP keys, if not NULL points to an array of * CFG80211_MAX_WEP_KEYS WEP keys * @wep_tx_key: key index (0..3) of the default TX static WEP key + * @psk: PSK (for devices supporting 4-way-handshake offload) */ struct cfg80211_crypto_settings { u32 wpa_versions; @@ -662,6 +663,7 @@ struct cfg80211_crypto_settings { bool control_port_no_encrypt; struct key_params *wep_keys; int wep_tx_key; + const u8 *psk; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b8c44b98f12d..f1f7da25bca4 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -172,6 +172,18 @@ * Multiple such rules can be created. */ +/** + * DOC: WPA/WPA2 EAPOL handshake offload + * + * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers + * can indicate they support offloading EAPOL handshakes for WPA/WPA2 + * preshared key authentication. In %NL80211_CMD_CONNECT the preshared + * key should be specified using %NL80211_ATTR_PMK. Drivers supporting + * this offload may reject the %NL80211_CMD_CONNECT when no preshared + * key material is provided, for example when that driver does not + * support setting the temporal keys through %CMD_NEW_KEY. + */ + /** * DOC: FILS shared key authentication offload * @@ -2080,8 +2092,10 @@ enum nl80211_commands { * identifying the scope of PMKSAs. This is used with * @NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA. * - * @NL80211_ATTR_PMK: PMK for the PMKSA identified by %NL80211_ATTR_PMKID. - * This is used with @NL80211_CMD_SET_PMKSA. + * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with + * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. + * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way + * handshake for WPA/WPA2-PSK networks. * * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to * indicate that it supports multiple active scheduled scan requests. @@ -4852,6 +4866,9 @@ enum nl80211_feature_flags { * RSSI threshold values to monitor rather than exactly one threshold. * @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD: Driver SME supports FILS shared key * authentication with %NL80211_CMD_CONNECT. + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device wants to do 4-way + * handshake with PSK in station mode (PSK is passed as part of the connect + * and associate commands), doing it in the host might not be supported. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -4872,6 +4889,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI, NL80211_EXT_FEATURE_CQM_RSSI_LIST, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9eb59196a378..2c6863aee4e4 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8168,6 +8168,15 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, memcpy(settings->akm_suites, data, len); } + if (info->attrs[NL80211_ATTR_PMK]) { + if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN) + return -EINVAL; + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK)) + return -EINVAL; + settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]); + } + return 0; } -- cgit v1.2.3 From 3a00df5707b6af715e78c26569800e0c2eb615fe Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Fri, 9 Jun 2017 13:08:43 +0100 Subject: cfg80211: support 4-way handshake offloading for 802.1X Add API for setting the PMK to the driver. For FT support, allow setting also the PMK-R0 Name. This can be used by drivers that support 4-Way handshake offload while IEEE802.1X authentication is managed by upper layers. Signed-off-by: Avraham Stern Signed-off-by: Johannes Berg [arend.vanspriel@broadcom.com: add WANT_1X_4WAY_HS attribute] Signed-off-by: Arend van Spriel [reword NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X docs a bit to say that the device may require it] Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 3 ++ include/net/cfg80211.h | 32 +++++++++++++ include/uapi/linux/nl80211.h | 39 +++++++++++++++- net/wireless/core.c | 5 +++ net/wireless/nl80211.c | 105 +++++++++++++++++++++++++++++++++++++++++++ net/wireless/rdev-ops.h | 25 +++++++++++ net/wireless/trace.h | 60 +++++++++++++++++++++++++ 7 files changed, 268 insertions(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index e97ca3a9a67b..34e1bcd2d7ff 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2400,8 +2400,11 @@ enum ieee80211_sa_query_action { #define WLAN_MAX_KEY_LEN 32 +#define WLAN_PMK_NAME_LEN 16 #define WLAN_PMKID_LEN 16 +#define WLAN_PMK_LEN_EAP_LEAP 16 #define WLAN_PMK_LEN 32 +#define WLAN_PMK_LEN_SUITE_B_192 48 #define WLAN_OUI_WFA 0x506f9a #define WLAN_OUI_TYPE_WFA_P2P 9 diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1b288bac5d1a..2174e51c6595 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2112,6 +2112,8 @@ struct cfg80211_bss_selection { * @fils_erp_rrk: ERP re-authentication Root Key (rRK) used to derive additional * keys in FILS or %NULL if not specified. * @fils_erp_rrk_len: Length of @fils_erp_rrk in octets. + * @want_1x: indicates user-space supports and wants to use 802.1X driver + * offload of 4-way handshake. */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -2144,6 +2146,7 @@ struct cfg80211_connect_params { u16 fils_erp_next_seq_num; const u8 *fils_erp_rrk; size_t fils_erp_rrk_len; + bool want_1x; }; /** @@ -2565,6 +2568,23 @@ struct cfg80211_nan_func { u64 cookie; }; +/** + * struct cfg80211_pmk_conf - PMK configuration + * + * @aa: authenticator address + * @pmk_len: PMK length in bytes. + * @pmk: the PMK material + * @pmk_r0_name: PMK-R0 Name. NULL if not applicable (i.e., the PMK + * is not PMK-R0). When pmk_r0_name is not NULL, the pmk field + * holds PMK-R0. + */ +struct cfg80211_pmk_conf { + const u8 *aa; + u8 pmk_len; + const u8 *pmk; + const u8 *pmk_r0_name; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -2881,6 +2901,13 @@ struct cfg80211_nan_func { * All other parameters must be ignored. * * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS + * + * @set_pmk: configure the PMK to be used for offloaded 802.1X 4-Way handshake. + * If not deleted through @del_pmk the PMK remains valid until disconnect + * upon which the driver should clear it. + * (invoked with the wireless_dev mutex held) + * @del_pmk: delete the previously configured PMK for the given authenticator. + * (invoked with the wireless_dev mutex held) */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -3169,6 +3196,11 @@ struct cfg80211_ops { int (*set_multicast_to_unicast)(struct wiphy *wiphy, struct net_device *dev, const bool enabled); + + int (*set_pmk)(struct wiphy *wiphy, struct net_device *dev, + const struct cfg80211_pmk_conf *conf); + int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev, + const u8 *aa); }; /* diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f1f7da25bca4..073e26850195 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -182,6 +182,17 @@ * this offload may reject the %NL80211_CMD_CONNECT when no preshared * key material is provided, for example when that driver does not * support setting the temporal keys through %CMD_NEW_KEY. + * + * Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be + * set by drivers indicating offload support of the PTK/GTK EAPOL + * handshakes during 802.1X authentication. In order to use the offload + * the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS + * attribute flag. Drivers supporting this offload may reject the + * %NL80211_CMD_CONNECT when the attribute flag is not present. + * + * For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK + * using %NL80211_CMD_SET_PMK. For offloaded FT support also + * %NL80211_ATTR_PMKR0_NAME must be provided. */ /** @@ -959,6 +970,14 @@ * does not result in a change for the current association. Currently, * only the %NL80211_ATTR_IE data is used and updated with this command. * + * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0 + * for the given authenticator address (specified with &NL80211_ATTR_MAC). + * When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the + * PMK-R0, otherwise it specifies the PMK. + * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously + * configured PMK for the authenticator address identified by + * &NL80211_ATTR_MAC. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1158,6 +1177,9 @@ enum nl80211_commands { NL80211_CMD_UPDATE_CONNECT_PARAMS, + NL80211_CMD_SET_PMK, + NL80211_CMD_DEL_PMK, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2095,13 +2117,20 @@ enum nl80211_commands { * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way - * handshake for WPA/WPA2-PSK networks. + * handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is + * used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute + * specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well. * * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to * indicate that it supports multiple active scheduled scan requests. * @NL80211_ATTR_SCHED_SCAN_MAX_REQS: indicates maximum number of scheduled * scan request that may be active for the device (u32). * + * @NL80211_ATTR_WANT_1X_4WAY_HS: flag attribute which user-space can include + * in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it + * wants to use the supported offload of the 4-way handshake. + * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2524,6 +2553,9 @@ enum nl80211_attrs { NL80211_ATTR_SCHED_SCAN_MULTI, NL80211_ATTR_SCHED_SCAN_MAX_REQS, + NL80211_ATTR_WANT_1X_4WAY_HS, + NL80211_ATTR_PMKR0_NAME, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4869,6 +4901,10 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device wants to do 4-way * handshake with PSK in station mode (PSK is passed as part of the connect * and associate commands), doing it in the host might not be supported. + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X: Device wants to do doing 4-way + * handshake with 802.1X in station mode (will pass EAP frames to the host + * and accept the set_pmk/del_pmk commands), doing it in the host might not + * be supported. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -4890,6 +4926,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_CQM_RSSI_LIST, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, diff --git a/net/wireless/core.c b/net/wireless/core.c index 83ea164f16b3..7b33e8c366bc 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -711,6 +711,11 @@ int wiphy_register(struct wiphy *wiphy) (wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2)))) return -EINVAL; + if (WARN_ON(wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X) && + (!rdev->ops->set_pmk || !rdev->ops->del_pmk))) + return -EINVAL; + if (wiphy->addresses) memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2c6863aee4e4..8148b01bcdd2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -8881,6 +8881,12 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) connect.privacy = info->attrs[NL80211_ATTR_PRIVACY]; + if (info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS] && + !wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X)) + return -EINVAL; + connect.want_1x = info->attrs[NL80211_ATTR_WANT_1X_4WAY_HS]; + err = nl80211_crypto_settings(rdev, info, &connect.crypto, NL80211_MAX_NR_CIPHER_SUITES); if (err) @@ -12265,6 +12271,90 @@ static int nl80211_set_multicast_to_unicast(struct sk_buff *skb, return rdev_set_multicast_to_unicast(rdev, dev, enabled); } +static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_pmk_conf pmk_conf = {}; + int ret; + + if (wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) + return -EOPNOTSUPP; + + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X)) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK]) + return -EINVAL; + + wdev_lock(wdev); + if (!wdev->current_bss) { + ret = -ENOTCONN; + goto out; + } + + pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]); + if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) { + ret = -EINVAL; + goto out; + } + + pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]); + pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]); + if (pmk_conf.pmk_len != WLAN_PMK_LEN && + pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) { + ret = -EINVAL; + goto out; + } + + if (info->attrs[NL80211_ATTR_PMKR0_NAME]) { + int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]); + + if (r0_name_len != WLAN_PMK_NAME_LEN) { + ret = -EINVAL; + goto out; + } + + pmk_conf.pmk_r0_name = + nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]); + } + + ret = rdev_set_pmk(rdev, dev, &pmk_conf); +out: + wdev_unlock(wdev); + return ret; +} + +static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + const u8 *aa; + int ret; + + if (wdev->iftype != NL80211_IFTYPE_STATION && + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) + return -EOPNOTSUPP; + + if (!wiphy_ext_feature_isset(&rdev->wiphy, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X)) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_MAC]) + return -EINVAL; + + wdev_lock(wdev); + aa = nla_data(info->attrs[NL80211_ATTR_MAC]); + ret = rdev_del_pmk(rdev, dev, aa); + wdev_unlock(wdev); + + return ret; +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -13140,6 +13230,21 @@ static const struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_SET_PMK, + .doit = nl80211_set_pmk, + .policy = nl80211_policy, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_DEL_PMK, + .doit = nl80211_del_pmk, + .policy = nl80211_policy, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + }; static struct genl_family nl80211_fam __ro_after_init = { diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 0598c1e5d0ad..ce23d7d49960 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -1164,4 +1164,29 @@ rdev_set_coalesce(struct cfg80211_registered_device *rdev, trace_rdev_return_int(&rdev->wiphy, ret); return ret; } + +static inline int rdev_set_pmk(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct cfg80211_pmk_conf *pmk_conf) +{ + int ret = -EOPNOTSUPP; + + trace_rdev_set_pmk(&rdev->wiphy, dev, pmk_conf); + if (rdev->ops->set_pmk) + ret = rdev->ops->set_pmk(&rdev->wiphy, dev, pmk_conf); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +} + +static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *aa) +{ + int ret = -EOPNOTSUPP; + + trace_rdev_del_pmk(&rdev->wiphy, dev, aa); + if (rdev->ops->del_pmk) + ret = rdev->ops->del_pmk(&rdev->wiphy, dev, aa); + trace_rdev_return_int(&rdev->wiphy, ret); + return ret; +} #endif /* __CFG80211_RDEV_OPS */ diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ca8b2059f92c..0f8db41eaddb 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2258,6 +2258,66 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch, WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr)) ); +TRACE_EVENT(rdev_set_pmk, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_pmk_conf *pmk_conf), + + TP_ARGS(wiphy, netdev, pmk_conf), + + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(aa) + __field(u8, pmk_len) + __field(u8, pmk_r0_name_len) + __dynamic_array(u8, pmk, pmk_conf->pmk_len) + __dynamic_array(u8, pmk_r0_name, WLAN_PMK_NAME_LEN) + ), + + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(aa, pmk_conf->aa); + __entry->pmk_len = pmk_conf->pmk_len; + __entry->pmk_r0_name_len = + pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0; + memcpy(__get_dynamic_array(pmk), pmk_conf->pmk, + pmk_conf->pmk_len); + memcpy(__get_dynamic_array(pmk_r0_name), pmk_conf->pmk_r0_name, + pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0); + ), + + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT + "pmk_len=%u, pmk: %s pmk_r0_name: %s", WIPHY_PR_ARG, + NETDEV_PR_ARG, MAC_PR_ARG(aa), __entry->pmk_len, + __print_array(__get_dynamic_array(pmk), + __get_dynamic_array_len(pmk), 1), + __entry->pmk_r0_name_len ? + __print_array(__get_dynamic_array(pmk_r0_name), + __get_dynamic_array_len(pmk_r0_name), 1) : "") +); + +TRACE_EVENT(rdev_del_pmk, + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *aa), + + TP_ARGS(wiphy, netdev, aa), + + TP_STRUCT__entry( + WIPHY_ENTRY + NETDEV_ENTRY + MAC_ENTRY(aa) + ), + + TP_fast_assign( + WIPHY_ASSIGN; + NETDEV_ASSIGN; + MAC_ASSIGN(aa, aa); + ), + + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT, + WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa)) +); + /************************************************************* * cfg80211 exported functions traces * *************************************************************/ -- cgit v1.2.3 From f45cbe6e691fcdeda480ecc9c66533a8277f0ca4 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Fri, 9 Jun 2017 13:08:45 +0100 Subject: nl80211: add authorized flag to ROAM event Drivers that initiate roaming while being connected to a network that uses 802.1X authentication need to inform user space if 802.1X authentication is further required after roaming. For example, when using the Fast transition protocol, roaming within the mobility domain does not require new 802.1X authentication, but roaming to another mobility domain does. In addition, some drivers may not support 802.1X authentication (so it has to be done in user space), while other drivers do. Add a flag to the roaming notification to indicate if user space is required to do 802.1X authentication after the roaming or not. This flag will only be used for networks that use 802.1X authentication. For networks that do not use 802.1X authentication it is assumed that no further action is required from user space after the roaming notification. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho [arend.vanspriel@broadcom.com reuse NL80211_ATTR_PORT_AUTHORIZED] Signed-off-by: Arend van Spriel [rebase to apply w/o the flag in CONNECT] Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 4 ++++ include/uapi/linux/nl80211.h | 11 +++++++++++ net/wireless/nl80211.c | 4 +++- net/wireless/sme.c | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include/net') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2174e51c6595..f12fa5245a45 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5441,6 +5441,9 @@ cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, * @req_ie_len: association request IEs length * @resp_ie: association response IEs (may be %NULL) * @resp_ie_len: assoc response IEs length + * @authorized: true if the 802.1X authentication was done by the driver or is + * not needed (e.g., when Fast Transition protocol was used), false + * otherwise. Ignored for networks that don't use 802.1X authentication. */ struct cfg80211_roam_info { struct ieee80211_channel *channel; @@ -5450,6 +5453,7 @@ struct cfg80211_roam_info { size_t req_ie_len; const u8 *resp_ie; size_t resp_ie_len; + bool authorized; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 073e26850195..72f15c3fc5a6 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -571,6 +571,12 @@ * well to remain backwards compatible. * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), * sent as an event when the card/driver roamed by itself. + * When used as an event, and the driver roamed in a network that requires + * 802.1X authentication, %NL80211_ATTR_PORT_AUTHORIZED should be set + * if the 802.1X authentication was done by the driver or if roaming was + * done using Fast Transition protocol (in which case 802.1X authentication + * is not needed). If %NL80211_ATTR_PORT_AUTHORIZED is not set, user space + * is responsible for the 802.1X authentication. * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify * userspace that a connection was dropped by the AP or due to other * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and @@ -2130,6 +2136,10 @@ enum nl80211_commands { * in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it * wants to use the supported offload of the 4-way handshake. * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. + * @NL80211_ATTR_PORT_AUTHORIZED: flag attribute used in %NL80211_CMD_ROAMED + * notification indicating that that 802.1X authentication was done by + * the driver or is not needed (because roaming used the Fast Transition + * protocol). * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined @@ -2555,6 +2565,7 @@ enum nl80211_attrs { NL80211_ATTR_WANT_1X_4WAY_HS, NL80211_ATTR_PMKR0_NAME, + NL80211_ATTR_PORT_AUTHORIZED, /* add attributes here, update the policy in nl80211.c */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8148b01bcdd2..5487cd775b6f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -13800,7 +13800,9 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev, info->req_ie)) || (info->resp_ie && nla_put(msg, NL80211_ATTR_RESP_IE, info->resp_ie_len, - info->resp_ie))) + info->resp_ie)) || + (info->authorized && + nla_put_flag(msg, NL80211_ATTR_PORT_AUTHORIZED))) goto nla_put_failure; genlmsg_end(msg, hdr); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 532a0007ce82..0a49b88070d0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -960,6 +960,7 @@ void cfg80211_roamed(struct net_device *dev, struct cfg80211_roam_info *info, ev->rm.resp_ie_len = info->resp_ie_len; memcpy((void *)ev->rm.resp_ie, info->resp_ie, info->resp_ie_len); ev->rm.bss = info->bss; + ev->rm.authorized = info->authorized; spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); -- cgit v1.2.3