diff options
author | Felix Fietkau <nbd@openwrt.org> | 2012-06-18 20:50:57 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-06-20 05:10:43 -0400 |
commit | 46c1dd0c7fac54d3739d62b6362024d9b568c6de (patch) | |
tree | 79f89f85ca9f6aff2efa1f7f1aed319ae3c1a51f /net/wireless/nl80211.c | |
parent | 2bd7e35da011f51d4fdb3b71f888c3a50194bfcd (diff) |
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>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | 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 06623d064606..888fadc4d63e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2335,6 +2335,33 @@ static int nl80211_parse_beacon(struct genl_info *info, | |||
2335 | return 0; | 2335 | return 0; |
2336 | } | 2336 | } |
2337 | 2337 | ||
2338 | static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev, | ||
2339 | struct cfg80211_ap_settings *params) | ||
2340 | { | ||
2341 | struct wireless_dev *wdev; | ||
2342 | bool ret = false; | ||
2343 | |||
2344 | mutex_lock(&rdev->devlist_mtx); | ||
2345 | |||
2346 | list_for_each_entry(wdev, &rdev->netdev_list, list) { | ||
2347 | if (wdev->iftype != NL80211_IFTYPE_AP && | ||
2348 | wdev->iftype != NL80211_IFTYPE_P2P_GO) | ||
2349 | continue; | ||
2350 | |||
2351 | if (!wdev->preset_chan) | ||
2352 | continue; | ||
2353 | |||
2354 | params->channel = wdev->preset_chan; | ||
2355 | params->channel_type = wdev->preset_chantype; | ||
2356 | ret = true; | ||
2357 | break; | ||
2358 | } | ||
2359 | |||
2360 | mutex_unlock(&rdev->devlist_mtx); | ||
2361 | |||
2362 | return ret; | ||
2363 | } | ||
2364 | |||
2338 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | 2365 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
2339 | { | 2366 | { |
2340 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2367 | 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) | |||
2437 | } else if (wdev->preset_chan) { | 2464 | } else if (wdev->preset_chan) { |
2438 | params.channel = wdev->preset_chan; | 2465 | params.channel = wdev->preset_chan; |
2439 | params.channel_type = wdev->preset_chantype; | 2466 | params.channel_type = wdev->preset_chantype; |
2440 | } else | 2467 | } else if (!nl80211_get_ap_channel(rdev, ¶ms)) |
2441 | return -EINVAL; | 2468 | return -EINVAL; |
2442 | 2469 | ||
2443 | if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, | 2470 | 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) | |||
2445 | return -EINVAL; | 2472 | return -EINVAL; |
2446 | 2473 | ||
2447 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); | 2474 | err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); |
2448 | if (!err) | 2475 | if (!err) { |
2476 | wdev->preset_chan = params.channel; | ||
2477 | wdev->preset_chantype = params.channel_type; | ||
2449 | wdev->beacon_interval = params.beacon_interval; | 2478 | wdev->beacon_interval = params.beacon_interval; |
2479 | } | ||
2450 | return err; | 2480 | return err; |
2451 | } | 2481 | } |
2452 | 2482 | ||