From: Peng Xu Date: Sat, 20 Jun 2015 00:19:27 +0000 (-0700) Subject: Fix generating offloaded ACS channel list when hw_mode is set to any X-Git-Tag: hostap_2_5~268 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=d0cdccd30785b2471c632c341caef68ab1bc62db;hp=844dfeb804af7e6934b5d8e5ffbe2e813dabff54;p=mech_eap.git Fix generating offloaded ACS channel list when hw_mode is set to any When ACS is offloaded to device driver and the hw_mode parameter is set to any, the current_mode structure is NULL which fails the ACS command. Fix this by populating the ACS channel list with channels from all bands when current_mode is NULL. Signed-off-by: Jouni Malinen --- diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index e417614..6cafcb7 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -743,6 +743,25 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd, } +static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, + struct hostapd_hw_modes *mode, + int acs_ch_list_all, + int **freq_list) +{ + int i; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + + if ((acs_ch_list_all || + freq_range_list_includes(&hapd->iface->conf->acs_ch_list, + chan->chan)) && + !(chan->flag & HOSTAPD_CHAN_DISABLED)) + int_array_add_unique(freq_list, chan->freq); + } +} + + int hostapd_drv_do_acs(struct hostapd_data *hapd) { struct drv_acs_params params; @@ -750,6 +769,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) u8 *channels = NULL; unsigned int num_channels = 0; struct hostapd_hw_modes *mode; + int *freq_list = NULL; if (hapd->driver == NULL || hapd->driver->do_acs == NULL) return 0; @@ -765,24 +785,35 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) acs_ch_list_all = 1; mode = hapd->iface->current_mode; - if (mode == NULL) - return -1; - channels = os_malloc(mode->num_channels); - if (channels == NULL) - return -1; - - for (i = 0; i < mode->num_channels; i++) { - struct hostapd_channel_data *chan = &mode->channels[i]; - if (!acs_ch_list_all && - !freq_range_list_includes(&hapd->iface->conf->acs_ch_list, - chan->chan)) - continue; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) - channels[num_channels++] = chan->chan; + if (mode) { + channels = os_malloc(mode->num_channels); + if (channels == NULL) + return -1; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (!acs_ch_list_all && + !freq_range_list_includes( + &hapd->iface->conf->acs_ch_list, + chan->chan)) + continue; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { + channels[num_channels++] = chan->chan; + int_array_add_unique(&freq_list, chan->freq); + } + } + } else { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + hostapd_get_hw_mode_any_channels(hapd, mode, + acs_ch_list_all, + &freq_list); + } } params.ch_list = channels; params.ch_list_len = num_channels; + params.freq_list = freq_list; params.ht_enabled = !!(hapd->iface->conf->ieee80211n); params.ht40_enabled = !!(hapd->iface->conf->ht_capab & diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 2a6e242..b9f5f84 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -223,6 +223,7 @@ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL, + QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST, /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ACS_MAX = diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 6e39aa3..e3d3229 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1602,6 +1602,7 @@ struct drv_acs_params { /* ACS channel list info */ unsigned int ch_list_len; const u8 *ch_list; + const int *freq_list; }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index a6441e3..15210ff 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8385,6 +8385,26 @@ static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode) } +static int add_acs_freq_list(struct nl_msg *msg, const int *freq_list) +{ + int i, len, ret; + u32 *freqs; + + if (!freq_list) + return 0; + len = int_array_len(freq_list); + freqs = os_malloc(sizeof(u32) * len); + if (!freqs) + return -1; + for (i = 0; i < len; i++) + freqs[i] = freq_list[i]; + ret = nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST, + sizeof(u32) * len, freqs); + os_free(freqs); + return ret; +} + + static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) { struct i802_bss *bss = priv; @@ -8414,7 +8434,8 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) params->ch_width) || (params->ch_list_len && nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len, - params->ch_list))) { + params->ch_list)) || + add_acs_freq_list(msg, params->freq_list)) { nlmsg_free(msg); return -ENOBUFS; }