mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-13 14:14:37 +00:00
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 <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
2bd7e35da0
commit
46c1dd0c7f
1 changed files with 32 additions and 2 deletions
|
@ -2335,6 +2335,33 @@ static int nl80211_parse_beacon(struct genl_info *info,
|
||||||
return 0;
|
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)
|
static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
|
@ -2437,7 +2464,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
} else if (wdev->preset_chan) {
|
} else if (wdev->preset_chan) {
|
||||||
params.channel = wdev->preset_chan;
|
params.channel = wdev->preset_chan;
|
||||||
params.channel_type = wdev->preset_chantype;
|
params.channel_type = wdev->preset_chantype;
|
||||||
} else
|
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
|
if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
|
||||||
|
@ -2445,8 +2472,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms);
|
err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms);
|
||||||
if (!err)
|
if (!err) {
|
||||||
|
wdev->preset_chan = params.channel;
|
||||||
|
wdev->preset_chantype = params.channel_type;
|
||||||
wdev->beacon_interval = params.beacon_interval;
|
wdev->beacon_interval = params.beacon_interval;
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue