diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9e63fc28f859..a7a78f28ff6f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1549,7 +1549,11 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, switch (sdata->vif.type) { 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; rcu_read_lock(); 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; break; case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: break; default: return -EOPNOTSUPP; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 46f371160896..caf11a427507 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -876,21 +876,53 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { - /* Verify that we are associated with the destination AP */ + int err = 0; + wdev_lock(wdev); - if (!wdev->current_bss || - memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, - ETH_ALEN) != 0 || - ((wdev->iftype == NL80211_IFTYPE_STATION || - wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && - memcmp(wdev->current_bss->pub.bssid, mgmt->da, - ETH_ALEN) != 0)) { - wdev_unlock(wdev); - return -ENOTCONN; - } + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: + if (!wdev->current_bss) { + err = -ENOTCONN; + break; + } + 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); + + if (err) + return err; } if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0087c4323c53..cbbbe9ab452f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -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 && 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; 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 && 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; goto out; }