Search Linux Wireless

[PATCH] cfg80211: fix regression in multi-vif AP start

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit "cfg80211: provide channel to start_ap function" assumes that the
channel is always passed to the NL80211_CMD_START_AP command, however
in case of multi-BSSID, hostapd only passes the channel for the first vif.
This makes starting beaconing on secondary vifs fail with -EINVAL.

Fix this by storing the channel provided to .start_ap in wdev->preset_chan
and picking the first AP vif's channel for secondary vifs if not provided.

Signed-off-by: Felix Fietkau <nbd@xxxxxxxxxxx>
---
 net/wireless/nl80211.c |   34 ++++++++++++++++++++++++++++++++--
 1 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7ae54b8..6f7d645 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2246,6 +2246,33 @@ static int nl80211_parse_beacon(struct genl_info *info,
 	return 0;
 }
 
+static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
+				   struct cfg80211_ap_settings *params)
+{
+	struct wireless_dev *wdev;
+	bool ret = false;
+
+	mutex_lock(&rdev->devlist_mtx);
+
+	list_for_each_entry(wdev, &rdev->netdev_list, list) {
+		if (wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+			continue;
+
+		if (!wdev->preset_chan)
+			continue;
+
+		params->channel = wdev->preset_chan;
+		params->channel_type = wdev->preset_chantype;
+		ret = true;
+		break;
+	}
+
+	mutex_unlock(&rdev->devlist_mtx);
+
+	return ret;
+}
+
 static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2348,7 +2375,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 	} else if (wdev->preset_chan) {
 		params.channel = wdev->preset_chan;
 		params.channel_type = wdev->preset_chantype;
-	} else
+	} else if (!nl80211_get_ap_channel(rdev, &params))
 		return -EINVAL;
 
 	if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
@@ -2356,8 +2383,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 
 	err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
-	if (!err)
+	if (!err) {
+		wdev->preset_chan = params.channel;
+		wdev->preset_chantype = params.channel_type;
 		wdev->beacon_interval = params.beacon_interval;
+	}
 	return err;
 }
 
-- 
1.7.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux