Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+6 −1
Original line number Original line Diff line number Diff line
@@ -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;
+43 −11
Original line number Original line Diff line number Diff line
@@ -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)
+8 −2
Original line number Original line Diff line number Diff line
@@ -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;
	}
	}