cfg80211/mac80211: allow management frame TX in AP mode
authorJohannes Berg <johannes.berg@intel.com>
Thu, 30 Sep 2010 19:06:09 +0000 (21:06 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 5 Oct 2010 17:35:23 +0000 (13:35 -0400)
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>
net/mac80211/cfg.c
net/wireless/mlme.c
net/wireless/nl80211.c

index 9e63fc2..a7a78f2 100644 (file)
@@ -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;
index 46f3711..caf11a4 100644 (file)
@@ -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)
index 0087c43..cbbbe9a 100644 (file)
@@ -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;
        }