2012-06-19 00:51:03

by Felix Fietkau

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

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 <[email protected]>
---
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



2012-06-20 09:11:37

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: fix regression in multi-vif AP start

On Tue, 2012-06-19 at 02:50 +0200, Felix Fietkau wrote:
> 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.

Applied, thanks.

johannes