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: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -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 @@
|
|||||||
* @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 {
|
|||||||
* @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 {
|
|||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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)
|
|||||||
.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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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);
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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] = {
|
|||||||
.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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
||||||
|
Reference in New Issue
Block a user