Commit 663fcafd authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4bd530f3
...@@ -1549,7 +1549,11 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
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