+
+
+int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
+ enum wpa_alg alg, const u8 *addr,
+ int key_idx, int set_tx,
+ const u8 *seq, size_t seq_len,
+ const u8 *key, size_t key_len)
+{
+ if (hapd->driver == NULL || hapd->driver->set_key == NULL)
+ return 0;
+ return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
+ key_idx, set_tx, seq, seq_len, key,
+ key_len);
+}
+
+
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
+ const void *msg, size_t len, int noack)
+{
+ if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+ return 0;
+ return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
+}
+
+
+int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
+ const u8 *addr, int reason)
+{
+ if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
+ return 0;
+ return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
+ reason);
+}
+
+
+int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
+ const u8 *addr, int reason)
+{
+ if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
+ return 0;
+ return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
+ reason);
+}
+
+
+int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
+ const u8 *peer, u8 *buf, u16 *buf_len)
+{
+ if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
+ return -1;
+ return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
+ buf_len);
+}
+
+
+int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
+ unsigned int wait, const u8 *dst, const u8 *data,
+ size_t len)
+{
+ if (hapd->driver == NULL || hapd->driver->send_action == NULL)
+ return 0;
+ return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
+ hapd->own_addr, hapd->own_addr, data,
+ len, 0);
+}
+
+
+int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+ enum hostapd_hw_mode mode, int freq,
+ int channel, int ht_enabled, int vht_enabled,
+ int sec_channel_offset, int vht_oper_chwidth,
+ int center_segment0, int center_segment1)
+{
+ struct hostapd_data *hapd = iface->bss[0];
+ struct hostapd_freq_params data;
+ int res;
+
+ if (!hapd->driver || !hapd->driver->start_dfs_cac)
+ return 0;
+
+ if (!iface->conf->ieee80211h) {
+ wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
+ "is not enabled");
+ return -1;
+ }
+
+ if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+ vht_enabled, sec_channel_offset,
+ vht_oper_chwidth, center_segment0,
+ center_segment1,
+ iface->current_mode->vht_capab)) {
+ wpa_printf(MSG_ERROR, "Can't set freq params");
+ return -1;
+ }
+
+ res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
+ if (!res) {
+ iface->cac_started = 1;
+ os_get_reltime(&iface->dfs_cac_start);
+ }
+
+ return res;
+}
+
+
+int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
+ const u8 *qos_map_set, u8 qos_map_set_len)
+{
+ if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL)
+ return 0;
+ return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
+ qos_map_set_len);
+}
+
+
+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;
+ int ret, i, acs_ch_list_all = 0;
+ 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;
+
+ os_memset(¶ms, 0, sizeof(params));
+ params.hw_mode = hapd->iface->conf->hw_mode;
+
+ /*
+ * If no chanlist config parameter is provided, include all enabled
+ * channels of the selected hw_mode.
+ */
+ if (!hapd->iface->conf->acs_ch_list.num)
+ acs_ch_list_all = 1;
+
+ mode = hapd->iface->current_mode;
+ 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 &
+ HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
+ params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
+ params.ch_width = 20;
+ if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
+ params.ch_width = 40;
+
+ /* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
+ */
+ if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
+ if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+ params.ch_width = 80;
+ else if (hapd->iface->conf->vht_oper_chwidth ==
+ VHT_CHANWIDTH_160MHZ ||
+ hapd->iface->conf->vht_oper_chwidth ==
+ VHT_CHANWIDTH_80P80MHZ)
+ params.ch_width = 160;
+ }
+
+ ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms);
+ os_free(channels);
+
+ return ret;
+}