aboutsummaryrefslogtreecommitdiff
path: root/src/ap/drv_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ap/drv_callbacks.c')
-rw-r--r--src/ap/drv_callbacks.c153
1 files changed, 113 insertions, 40 deletions
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index f353a0ed..8fc128e9 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -261,12 +261,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* NEED_AP_MLME */
-#ifdef CONFIG_INTERWORKING
- if (elems.ext_capab && elems.ext_capab_len > 4) {
- if (elems.ext_capab[4] & 0x01)
- sta->qos_map_enabled = 1;
- }
-#endif /* CONFIG_INTERWORKING */
+ check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
#ifdef CONFIG_HS20
wpabuf_free(sta->hs20_ie);
@@ -345,6 +340,16 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* CONFIG_WPS */
+ if (check_sa_query_need(hapd, sta)) {
+ status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
+
+ p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
+
+ hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
+ p - buf);
+ return 0;
+ }
+
if (sta->wpa_sm == NULL)
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
sta->addr,
@@ -425,16 +430,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
- if (check_sa_query_need(hapd, sta)) {
- status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
-
- p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
-
- hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
- p - buf);
- return 0;
- }
-
if (wpa_auth_uses_mfp(sta->wpa_sm))
sta->flags |= WLAN_STA_MFP;
else
@@ -456,7 +451,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_SAE
- if (hapd->conf->sae_pwe == 2 &&
+ if (hapd->conf->sae_pwe == SAE_PWE_BOTH &&
sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e &&
ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
@@ -843,6 +838,9 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
case CHAN_WIDTH_160:
txt = "160";
break;
+ case CHAN_WIDTH_320:
+ txt = "320";
+ break;
default:
txt = NULL;
break;
@@ -861,20 +859,23 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2,
- int finished)
+ u16 punct_bitmap, int finished)
{
#ifdef NEED_AP_MLME
- int channel, chwidth, is_dfs;
+ int channel, chwidth, is_dfs0, is_dfs;
u8 seg0_idx = 0, seg1_idx = 0;
size_t i;
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
- "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+ "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, puncturing_bitmap=0x%x",
finished ? "had" : "starting",
+ hapd->iface->freq,
freq, ht, hapd->iconf->ch_switch_vht_config,
- hapd->iconf->ch_switch_he_config, offset,
- width, channel_width_to_string(width), cf1, cf2);
+ hapd->iconf->ch_switch_he_config,
+ hapd->iconf->ch_switch_eht_config, offset,
+ width, channel_width_to_string(width), cf1, cf2,
+ punct_bitmap);
if (!hapd->iface->current_mode) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
@@ -883,6 +884,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
return;
}
+ /* Check if any of configured channels require DFS */
+ is_dfs0 = hostapd_is_dfs_required(hapd->iface);
hapd->iface->freq = freq;
channel = hostapd_hw_get_channel(hapd, freq);
@@ -895,19 +898,22 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
switch (width) {
case CHAN_WIDTH_80:
- chwidth = CHANWIDTH_80MHZ;
+ chwidth = CONF_OPER_CHWIDTH_80MHZ;
break;
case CHAN_WIDTH_80P80:
- chwidth = CHANWIDTH_80P80MHZ;
+ chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
break;
case CHAN_WIDTH_160:
- chwidth = CHANWIDTH_160MHZ;
+ chwidth = CONF_OPER_CHWIDTH_160MHZ;
+ break;
+ case CHAN_WIDTH_320:
+ chwidth = CONF_OPER_CHWIDTH_320MHZ;
break;
case CHAN_WIDTH_20_NOHT:
case CHAN_WIDTH_20:
case CHAN_WIDTH_40:
default:
- chwidth = CHANWIDTH_USE_HT;
+ chwidth = CONF_OPER_CHWIDTH_USE_HT;
break;
}
@@ -953,9 +959,23 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
else if (hapd->iconf->ch_switch_he_config &
CH_SWITCH_HE_DISABLED)
hapd->iconf->ieee80211ax = 0;
+#ifdef CONFIG_IEEE80211BE
+ } else if (hapd->iconf->ch_switch_eht_config) {
+ /* CHAN_SWITCH EHT config */
+ if (hapd->iconf->ch_switch_eht_config &
+ CH_SWITCH_EHT_ENABLED) {
+ hapd->iconf->ieee80211be = 1;
+ hapd->iconf->ieee80211ax = 1;
+ if (!is_6ghz_freq(hapd->iface->freq))
+ hapd->iconf->ieee80211ac = 1;
+ } else if (hapd->iconf->ch_switch_eht_config &
+ CH_SWITCH_EHT_DISABLED)
+ hapd->iconf->ieee80211be = 0;
+#endif /* CONFIG_IEEE80211BE */
}
hapd->iconf->ch_switch_vht_config = 0;
hapd->iconf->ch_switch_he_config = 0;
+ hapd->iconf->ch_switch_eht_config = 0;
if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 ||
width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160)
@@ -967,12 +987,15 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
+#ifdef CONFIG_IEEE80211BE
+ hapd->iconf->punct_bitmap = punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
if (hapd->iconf->ieee80211ac) {
hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (chwidth == CHANWIDTH_160MHZ)
+ if (chwidth == CONF_OPER_CHWIDTH_160MHZ)
hapd->iconf->vht_capab |=
VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
- else if (chwidth == CHANWIDTH_80P80MHZ)
+ else if (chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
hapd->iconf->vht_capab |=
VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
}
@@ -981,11 +1004,11 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hapd->iface->num_hw_features);
wpa_msg(hapd->msg_ctx, MSG_INFO,
- "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d",
+ "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d is_dfs0=%d dfs=%d puncturing_bitmap=0x%04x",
finished ? WPA_EVENT_CHANNEL_SWITCH :
WPA_EVENT_CHANNEL_SWITCH_STARTED,
freq, ht, offset, channel_width_to_string(width),
- cf1, cf2, is_dfs);
+ cf1, cf2, is_dfs0, is_dfs, punct_bitmap);
if (!finished)
return;
@@ -997,6 +1020,14 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
"freq=%d dfs=%d", freq, is_dfs);
} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+ /* Complete AP configuration for the first bring up. */
+ if (is_dfs0 > 0 &&
+ hostapd_is_dfs_required(hapd->iface) <= 0 &&
+ hapd->iface->state != HAPD_IFACE_ENABLED) {
+ /* Fake a CAC start bit to skip setting channel */
+ hapd->iface->cac_started = 1;
+ hostapd_setup_interface_complete(hapd->iface, 0);
+ }
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
"freq=%d dfs=%d", freq, is_dfs);
} else if (is_dfs &&
@@ -1011,7 +1042,9 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hostapd_neighbor_set_own_report(hapd->iface->bss[i]);
#ifdef CONFIG_OCV
- if (hapd->conf->ocv) {
+ if (hapd->conf->ocv &&
+ !(hapd->iface->drv_flags2 &
+ WPA_DRIVER_FLAGS2_SA_QUERY_OFFLOAD_AP)) {
struct sta_info *sta;
bool check_sa_query = false;
@@ -1133,7 +1166,7 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
/* set defaults for backwards compatibility */
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0);
- hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT);
+ hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_USE_HT);
if (acs_res->ch_width == 40) {
if (is_6ghz_freq(acs_res->pri_freq))
hostapd_set_oper_centr_freq_seg0_idx(
@@ -1143,22 +1176,33 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
hostapd_set_oper_centr_freq_seg0_idx(
hapd->iconf, acs_res->vht_seg0_center_ch);
if (acs_res->vht_seg1_center_ch == 0) {
- hostapd_set_oper_chwidth(hapd->iconf,
- CHANWIDTH_80MHZ);
+ hostapd_set_oper_chwidth(
+ hapd->iconf, CONF_OPER_CHWIDTH_80MHZ);
} else {
- hostapd_set_oper_chwidth(hapd->iconf,
- CHANWIDTH_80P80MHZ);
+ hostapd_set_oper_chwidth(
+ hapd->iconf,
+ CONF_OPER_CHWIDTH_80P80MHZ);
hostapd_set_oper_centr_freq_seg1_idx(
hapd->iconf,
acs_res->vht_seg1_center_ch);
}
} else if (acs_res->ch_width == 160) {
- hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_160MHZ);
+ hostapd_set_oper_chwidth(hapd->iconf,
+ CONF_OPER_CHWIDTH_160MHZ);
hostapd_set_oper_centr_freq_seg0_idx(
hapd->iconf, acs_res->vht_seg1_center_ch);
}
}
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->iface->conf->ieee80211be && acs_res->ch_width == 320) {
+ hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_320MHZ);
+ hostapd_set_oper_centr_freq_seg0_idx(
+ hapd->iconf, acs_res->vht_seg1_center_ch);
+ hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
+ }
+#endif /* CONFIG_IEEE80211BE */
+
out:
ret = hostapd_acs_completed(hapd->iface, err);
if (ret) {
@@ -1531,7 +1575,8 @@ static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
- const u8 *data, size_t data_len)
+ const u8 *data, size_t data_len,
+ enum frame_encryption encrypted)
{
struct hostapd_iface *iface = hapd->iface;
struct sta_info *sta;
@@ -1545,7 +1590,7 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
}
}
- ieee802_1x_receive(hapd, src, data, data_len);
+ ieee802_1x_receive(hapd, src, data, data_len, encrypted);
}
#endif /* HOSTAPD */
@@ -1940,7 +1985,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_EAPOL_RX:
hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
data->eapol_rx.data,
- data->eapol_rx.data_len);
+ data->eapol_rx.data_len,
+ data->eapol_rx.encrypted);
break;
case EVENT_ASSOC:
if (!data)
@@ -1985,6 +2031,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->ch_switch.ch_width,
data->ch_switch.cf1,
data->ch_switch.cf2,
+ data->ch_switch.punct_bitmap,
event == EVENT_CH_SWITCH);
break;
case EVENT_CONNECT_FAILED_REASON:
@@ -2084,6 +2131,32 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->wds_sta_interface.ifname,
data->wds_sta_interface.sta_addr);
break;
+#ifdef CONFIG_IEEE80211AX
+ case EVENT_BSS_COLOR_COLLISION:
+ /* The BSS color is shared amongst all BBSs on a specific phy.
+ * Therefore we always start the color change on the primary
+ * BSS. */
+ wpa_printf(MSG_DEBUG, "BSS color collision on %s",
+ hapd->conf->iface);
+ hostapd_switch_color(hapd->iface->bss[0],
+ data->bss_color_collision.bitmap);
+ break;
+ case EVENT_CCA_STARTED_NOTIFY:
+ wpa_printf(MSG_DEBUG, "CCA started on on %s",
+ hapd->conf->iface);
+ break;
+ case EVENT_CCA_ABORTED_NOTIFY:
+ wpa_printf(MSG_DEBUG, "CCA aborted on on %s",
+ hapd->conf->iface);
+ hostapd_cleanup_cca_params(hapd);
+ break;
+ case EVENT_CCA_NOTIFY:
+ wpa_printf(MSG_DEBUG, "CCA finished on on %s",
+ hapd->conf->iface);
+ hapd->iface->conf->he_op.he_bss_color = hapd->cca_color;
+ hostapd_cleanup_cca_params(hapd);
+ break;
+#endif /* CONFIG_IEEE80211AX */
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;