Commit 5ac9efbe authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-next-for-davem-2016-12-09' of...

Merge tag 'mac80211-next-for-davem-2016-12-09' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
Three fixes:
 * fix a logic bug introduced by a previous cleanup
 * fix nl80211 attribute confusing (trying to use
   a single attribute for two purposes)
 * fix a long-standing BSS leak that happens when an
   association attempt is abandoned
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 524a64c7 e6f462df
...@@ -4685,6 +4685,17 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, ...@@ -4685,6 +4685,17 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
*/ */
void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss); void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss);
/**
* cfg80211_abandon_assoc - notify cfg80211 of abandoned association attempt
* @dev: network device
* @bss: The BSS entry with which association was abandoned.
*
* Call this whenever - for reasons reported through other API, like deauth RX,
* an association attempt was abandoned.
* This function may sleep. The caller must hold the corresponding wdev's mutex.
*/
void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss);
/** /**
* cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
* @dev: network device * @dev: network device
......
...@@ -323,7 +323,7 @@ ...@@ -323,7 +323,7 @@
* @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_GET_SCAN: get scan results
* @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
* %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
* probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to * probe requests at CCK rate or not. %NL80211_ATTR_BSSID can be used to
* specify a BSSID to scan for; if not included, the wildcard BSSID will * specify a BSSID to scan for; if not included, the wildcard BSSID will
* be used. * be used.
* @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
...@@ -1977,6 +1977,9 @@ enum nl80211_commands { ...@@ -1977,6 +1977,9 @@ enum nl80211_commands {
* @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
* packets should be send out as unicast to all stations (flag attribute). * packets should be send out as unicast to all stations (flag attribute).
* *
* @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
* used in various commands/events for specifying the BSSID.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
...@@ -2381,6 +2384,8 @@ enum nl80211_attrs { ...@@ -2381,6 +2384,8 @@ enum nl80211_attrs {
NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED, NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
NL80211_ATTR_BSSID,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
......
...@@ -2518,7 +2518,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, ...@@ -2518,7 +2518,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
} }
static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
bool assoc) bool assoc, bool abandon)
{ {
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
...@@ -2541,6 +2541,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, ...@@ -2541,6 +2541,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
mutex_lock(&sdata->local->mtx); mutex_lock(&sdata->local->mtx);
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
mutex_unlock(&sdata->local->mtx); mutex_unlock(&sdata->local->mtx);
if (abandon)
cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
} }
kfree(assoc_data); kfree(assoc_data);
...@@ -2773,7 +2776,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ...@@ -2773,7 +2776,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
bssid, reason_code, bssid, reason_code,
ieee80211_get_reason_code_string(reason_code)); ieee80211_get_reason_code_string(reason_code));
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, true);
cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
return; return;
...@@ -3182,14 +3185,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ...@@ -3182,14 +3185,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (status_code != WLAN_STATUS_SUCCESS) { if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied association (code=%d)\n", sdata_info(sdata, "%pM denied association (code=%d)\n",
mgmt->sa, status_code); mgmt->sa, status_code);
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, false);
event.u.mlme.status = MLME_DENIED; event.u.mlme.status = MLME_DENIED;
event.u.mlme.reason = status_code; event.u.mlme.reason = status_code;
drv_event_callback(sdata->local, sdata, &event); drv_event_callback(sdata->local, sdata, &event);
} else { } else {
if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */ /* oops -- internal error -- send timeout for now */
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss); cfg80211_assoc_timeout(sdata->dev, bss);
return; return;
} }
...@@ -3202,7 +3205,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ...@@ -3202,7 +3205,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
* recalc after assoc_data is NULL but before associated * recalc after assoc_data is NULL but before associated
* is set can cause the interface to go idle * is set can cause the interface to go idle
*/ */
ieee80211_destroy_assoc_data(sdata, true); ieee80211_destroy_assoc_data(sdata, true, false);
/* get uapsd queues configuration */ /* get uapsd queues configuration */
uapsd_queues = 0; uapsd_queues = 0;
...@@ -3901,7 +3904,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) ...@@ -3901,7 +3904,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
.u.mlme.status = MLME_TIMEOUT, .u.mlme.status = MLME_TIMEOUT,
}; };
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss); cfg80211_assoc_timeout(sdata->dev, bss);
drv_event_callback(sdata->local, sdata, &event); drv_event_callback(sdata->local, sdata, &event);
} }
...@@ -4040,7 +4043,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) ...@@ -4040,7 +4043,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
WLAN_REASON_DEAUTH_LEAVING, WLAN_REASON_DEAUTH_LEAVING,
false, frame_buf); false, frame_buf);
if (ifmgd->assoc_data) if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, true);
if (ifmgd->auth_data) if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false); ieee80211_destroy_auth_data(sdata, false);
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
...@@ -4949,7 +4952,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ...@@ -4949,7 +4952,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
IEEE80211_STYPE_DEAUTH, IEEE80211_STYPE_DEAUTH,
req->reason_code, tx, req->reason_code, tx,
frame_buf); frame_buf);
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, true);
ieee80211_report_disconnect(sdata, frame_buf, ieee80211_report_disconnect(sdata, frame_buf,
sizeof(frame_buf), true, sizeof(frame_buf), true,
req->reason_code); req->reason_code);
...@@ -5024,7 +5027,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) ...@@ -5024,7 +5027,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
sdata_lock(sdata); sdata_lock(sdata);
if (ifmgd->assoc_data) { if (ifmgd->assoc_data) {
struct cfg80211_bss *bss = ifmgd->assoc_data->bss; struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
ieee80211_destroy_assoc_data(sdata, false); ieee80211_destroy_assoc_data(sdata, false, false);
cfg80211_assoc_timeout(sdata->dev, bss); cfg80211_assoc_timeout(sdata->dev, bss);
} }
if (ifmgd->auth_data) if (ifmgd->auth_data)
......
...@@ -410,6 +410,7 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev); ...@@ -410,6 +410,7 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev);
void cfg80211_sme_deauth(struct wireless_dev *wdev); void cfg80211_sme_deauth(struct wireless_dev *wdev);
void cfg80211_sme_auth_timeout(struct wireless_dev *wdev); void cfg80211_sme_auth_timeout(struct wireless_dev *wdev);
void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev); void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev);
void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
/* internal helpers */ /* internal helpers */
bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
......
...@@ -149,6 +149,18 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss) ...@@ -149,6 +149,18 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
} }
EXPORT_SYMBOL(cfg80211_assoc_timeout); EXPORT_SYMBOL(cfg80211_assoc_timeout);
void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
cfg80211_sme_abandon_assoc(wdev);
cfg80211_unhold_bss(bss_from_pub(bss));
cfg80211_put_bss(wiphy, bss);
}
EXPORT_SYMBOL(cfg80211_abandon_assoc);
void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len) void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
......
...@@ -404,6 +404,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -404,6 +404,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.len = FILS_MAX_KEK_LEN }, .len = FILS_MAX_KEK_LEN },
[NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN }, [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, }, [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
[NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
}; };
/* policy for the key attributes */ /* policy for the key attributes */
...@@ -6703,7 +6704,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) ...@@ -6703,7 +6704,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->no_cck = request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
if (info->attrs[NL80211_ATTR_MAC]) /* Initial implementation used NL80211_ATTR_MAC to set the specific
* BSSID to scan for. This was problematic because that same attribute
* was already used for another purpose (local random MAC address). The
* NL80211_ATTR_BSSID attribute was added to fix this. For backwards
* compatibility with older userspace components, also use the
* NL80211_ATTR_MAC value here if it can be determined to be used for
* the specific BSSID use case instead of the random MAC address
* (NL80211_ATTR_SCAN_FLAGS is used to enable random MAC address use).
*/
if (info->attrs[NL80211_ATTR_BSSID])
memcpy(request->bssid,
nla_data(info->attrs[NL80211_ATTR_BSSID]), ETH_ALEN);
else if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) &&
info->attrs[NL80211_ATTR_MAC])
memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]), memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
ETH_ALEN); ETH_ALEN);
else else
...@@ -10628,7 +10642,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info) ...@@ -10628,7 +10642,7 @@ static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
if (wdev->iftype != NL80211_IFTYPE_NAN) if (wdev->iftype != NL80211_IFTYPE_NAN)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!wdev_running(wdev)) if (wdev_running(wdev))
return -EEXIST; return -EEXIST;
if (rfkill_blocked(rdev->rfkill)) if (rfkill_blocked(rdev->rfkill))
......
...@@ -39,6 +39,7 @@ struct cfg80211_conn { ...@@ -39,6 +39,7 @@ struct cfg80211_conn {
CFG80211_CONN_ASSOCIATING, CFG80211_CONN_ASSOCIATING,
CFG80211_CONN_ASSOC_FAILED, CFG80211_CONN_ASSOC_FAILED,
CFG80211_CONN_DEAUTH, CFG80211_CONN_DEAUTH,
CFG80211_CONN_ABANDON,
CFG80211_CONN_CONNECTED, CFG80211_CONN_CONNECTED,
} state; } state;
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
...@@ -206,6 +207,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) ...@@ -206,6 +207,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
NULL, 0, NULL, 0,
WLAN_REASON_DEAUTH_LEAVING, false); WLAN_REASON_DEAUTH_LEAVING, false);
/* fall through */
case CFG80211_CONN_ABANDON:
/* free directly, disconnected event already sent */ /* free directly, disconnected event already sent */
cfg80211_sme_free(wdev); cfg80211_sme_free(wdev);
return 0; return 0;
...@@ -423,6 +426,17 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) ...@@ -423,6 +426,17 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
schedule_work(&rdev->conn_work); schedule_work(&rdev->conn_work);
} }
void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
if (!wdev->conn)
return;
wdev->conn->state = CFG80211_CONN_ABANDON;
schedule_work(&rdev->conn_work);
}
static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev, static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
const u8 *ies, size_t ies_len, const u8 *ies, size_t ies_len,
const u8 **out_ies, size_t *out_ies_len) const u8 **out_ies, size_t *out_ies_len)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment