Commit abe3a2c9 authored by Jonas Dreßler's avatar Jonas Dreßler Committed by Kalle Valo
Browse files

mwifiex: Use function to check whether interface type change is allowed



Instead of bailing out in the function which is supposed to do the type
change, detect invalid changes beforehand using a generic function and
return an error if the change is not allowed.

Signed-off-by: default avatarJonas Dreßler <verdre@v0yd.nl>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210914195909.36035-3-verdre@v0yd.nl
parent babe2a33
Loading
Loading
Loading
Loading
+92 −47
Original line number Diff line number Diff line
@@ -939,6 +939,76 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
	return 0;
}

static bool
is_vif_type_change_allowed(struct mwifiex_adapter *adapter,
			   enum nl80211_iftype old_iftype,
			   enum nl80211_iftype new_iftype)
{
	switch (old_iftype) {
	case NL80211_IFTYPE_ADHOC:
		switch (new_iftype) {
		case NL80211_IFTYPE_STATION:
			return true;
		case NL80211_IFTYPE_P2P_CLIENT:
		case NL80211_IFTYPE_P2P_GO:
			return adapter->curr_iface_comb.p2p_intf !=
			       adapter->iface_limit.p2p_intf;
		case NL80211_IFTYPE_AP:
			return adapter->curr_iface_comb.uap_intf !=
			       adapter->iface_limit.uap_intf;
		default:
			return false;
		}

	case NL80211_IFTYPE_STATION:
		switch (new_iftype) {
		case NL80211_IFTYPE_ADHOC:
			return true;
		case NL80211_IFTYPE_P2P_CLIENT:
		case NL80211_IFTYPE_P2P_GO:
			return adapter->curr_iface_comb.p2p_intf !=
			       adapter->iface_limit.p2p_intf;
		case NL80211_IFTYPE_AP:
			return adapter->curr_iface_comb.uap_intf !=
			       adapter->iface_limit.uap_intf;
		default:
			return false;
		}

	case NL80211_IFTYPE_AP:
		switch (new_iftype) {
		case NL80211_IFTYPE_ADHOC:
		case NL80211_IFTYPE_STATION:
			return adapter->curr_iface_comb.sta_intf !=
			       adapter->iface_limit.sta_intf;
		case NL80211_IFTYPE_P2P_CLIENT:
		case NL80211_IFTYPE_P2P_GO:
			return adapter->curr_iface_comb.p2p_intf !=
			       adapter->iface_limit.p2p_intf;
		default:
			return false;
		}

	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_P2P_GO:
		switch (new_iftype) {
		case NL80211_IFTYPE_ADHOC:
		case NL80211_IFTYPE_STATION:
			return true;
		case NL80211_IFTYPE_AP:
			return adapter->curr_iface_comb.uap_intf !=
			       adapter->iface_limit.uap_intf;
		default:
			return false;
		}

	default:
		break;
	}

	return false;
}

static int
mwifiex_change_vif_to_p2p(struct net_device *dev,
			  enum nl80211_iftype curr_iftype,
@@ -955,13 +1025,6 @@ mwifiex_change_vif_to_p2p(struct net_device *dev,

	adapter = priv->adapter;

	if (adapter->curr_iface_comb.p2p_intf ==
	    adapter->iface_limit.p2p_intf) {
		mwifiex_dbg(adapter, ERROR,
			    "cannot create multiple P2P ifaces\n");
		return -1;
	}

	mwifiex_dbg(adapter, INFO,
		    "%s: changing role to p2p\n", dev->name);

@@ -1027,15 +1090,6 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,

	adapter = priv->adapter;

	if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
	     curr_iftype != NL80211_IFTYPE_P2P_GO) &&
	    (adapter->curr_iface_comb.sta_intf ==
	     adapter->iface_limit.sta_intf)) {
		mwifiex_dbg(adapter, ERROR,
			    "cannot create multiple station/adhoc ifaces\n");
		return -1;
	}

	if (type == NL80211_IFTYPE_STATION)
		mwifiex_dbg(adapter, INFO,
			    "%s: changing role to station\n", dev->name);
@@ -1086,13 +1140,6 @@ mwifiex_change_vif_to_ap(struct net_device *dev,

	adapter = priv->adapter;

	if (adapter->curr_iface_comb.uap_intf ==
	    adapter->iface_limit.uap_intf) {
		mwifiex_dbg(adapter, ERROR,
			    "cannot create multiple AP ifaces\n");
		return -1;
	}

	mwifiex_dbg(adapter, INFO,
		    "%s: changing role to AP\n", dev->name);

@@ -1155,6 +1202,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
		return 0;
	}

	if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) {
		mwifiex_dbg(priv->adapter, ERROR,
			    "%s: change from type %d to %d is not allowed\n",
			    dev->name, curr_iftype, type);
		return -EOPNOTSUPP;
	}

	switch (curr_iftype) {
	case NL80211_IFTYPE_ADHOC:
		switch (type) {
@@ -1175,12 +1229,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
							params);
		default:
			mwifiex_dbg(priv->adapter, ERROR,
				    "%s: changing to %d not supported\n",
				    dev->name, type);
			return -EOPNOTSUPP;
			goto errnotsupp;
		}
		break;

	case NL80211_IFTYPE_STATION:
		switch (type) {
		case NL80211_IFTYPE_ADHOC:
@@ -1200,12 +1251,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
							params);
		default:
			mwifiex_dbg(priv->adapter, ERROR,
				    "%s: changing to %d not supported\n",
				    dev->name, type);
			return -EOPNOTSUPP;
			goto errnotsupp;
		}
		break;

	case NL80211_IFTYPE_AP:
		switch (type) {
		case NL80211_IFTYPE_ADHOC:
@@ -1217,12 +1265,9 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
			return mwifiex_change_vif_to_p2p(dev, curr_iftype,
							 type, params);
		default:
			mwifiex_dbg(priv->adapter, ERROR,
				    "%s: changing to %d not supported\n",
				    dev->name, type);
			return -EOPNOTSUPP;
			goto errnotsupp;
		}
		break;

	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_P2P_GO:
		switch (type) {
@@ -1251,21 +1296,21 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
							params);
		default:
			mwifiex_dbg(priv->adapter, ERROR,
				    "%s: changing to %d not supported\n",
				    dev->name, type);
			return -EOPNOTSUPP;
			goto errnotsupp;
		}
		break;

	default:
		mwifiex_dbg(priv->adapter, ERROR,
			    "%s: unknown iftype: %d\n",
			    dev->name, dev->ieee80211_ptr->iftype);
		return -EOPNOTSUPP;
		goto errnotsupp;
	}


	return 0;

errnotsupp:
	mwifiex_dbg(priv->adapter, ERROR,
		    "unsupported interface type transition: %d to %d\n",
		    curr_iftype, type);
	return -EOPNOTSUPP;
}

static void