cfg80211/mac80211: allow management frame TX in AP mode
Enable management frame transmission and subscribing to management frames through nl80211 in both cfg80211 and mac80211. Also update a few places that I forgot to update for P2P-client mode previously, and fix a small bug with non-action frames in this API. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
4bd530f3ab
commit
663fcafd97
@@ -1549,7 +1549,11 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
|
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
|
case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
case NL80211_IFTYPE_P2P_GO:
|
||||||
|
if (!ieee80211_is_action(mgmt->frame_control) ||
|
||||||
|
mgmt->u.action.category == WLAN_CATEGORY_PUBLIC)
|
||||||
break;
|
break;
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sta = sta_info_get(sdata, mgmt->da);
|
sta = sta_info_get(sdata, mgmt->da);
|
||||||
@@ -1558,6 +1562,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
return -ENOLINK;
|
return -ENOLINK;
|
||||||
break;
|
break;
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@@ -876,21 +876,53 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
|
|||||||
|
|
||||||
if (ieee80211_is_action(mgmt->frame_control) &&
|
if (ieee80211_is_action(mgmt->frame_control) &&
|
||||||
mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
|
mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) {
|
||||||
/* Verify that we are associated with the destination AP */
|
int err = 0;
|
||||||
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
if (!wdev->current_bss ||
|
switch (wdev->iftype) {
|
||||||
memcmp(wdev->current_bss->pub.bssid, mgmt->bssid,
|
case NL80211_IFTYPE_ADHOC:
|
||||||
ETH_ALEN) != 0 ||
|
case NL80211_IFTYPE_STATION:
|
||||||
((wdev->iftype == NL80211_IFTYPE_STATION ||
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
|
if (!wdev->current_bss) {
|
||||||
memcmp(wdev->current_bss->pub.bssid, mgmt->da,
|
err = -ENOTCONN;
|
||||||
ETH_ALEN) != 0)) {
|
break;
|
||||||
wdev_unlock(wdev);
|
}
|
||||||
return -ENOTCONN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (memcmp(wdev->current_bss->pub.bssid,
|
||||||
|
mgmt->bssid, ETH_ALEN)) {
|
||||||
|
err = -ENOTCONN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check for IBSS DA must be done by driver as
|
||||||
|
* cfg80211 doesn't track the stations
|
||||||
|
*/
|
||||||
|
if (wdev->iftype == NL80211_IFTYPE_ADHOC)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* for station, check that DA is the AP */
|
||||||
|
if (memcmp(wdev->current_bss->pub.bssid,
|
||||||
|
mgmt->da, ETH_ALEN)) {
|
||||||
|
err = -ENOTCONN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_IFTYPE_AP:
|
||||||
|
case NL80211_IFTYPE_P2P_GO:
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN))
|
||||||
|
err = -EINVAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err = -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
|
if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0)
|
||||||
|
@@ -4828,7 +4828,10 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||||||
|
|
||||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
|
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
|
||||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
|
||||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) {
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -4881,7 +4884,10 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||||||
|
|
||||||
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
|
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
|
||||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
|
||||||
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) {
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
|
||||||
|
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user