diff options
Diffstat (limited to 'src/ap/ap_drv_ops.c')
-rw-r--r-- | src/ap/ap_drv_ops.c | 228 |
1 files changed, 130 insertions, 98 deletions
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 6cafcb749351..f1394654d3a8 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -33,10 +33,36 @@ u32 hostapd_sta_flags_to_drv(u32 flags) res |= WPA_STA_SHORT_PREAMBLE; if (flags & WLAN_STA_MFP) res |= WPA_STA_MFP; + if (flags & WLAN_STA_AUTH) + res |= WPA_STA_AUTHENTICATED; + if (flags & WLAN_STA_ASSOC) + res |= WPA_STA_ASSOCIATED; return res; } +static int add_buf(struct wpabuf **dst, const struct wpabuf *src) +{ + if (!src) + return 0; + if (wpabuf_resize(dst, wpabuf_len(src)) != 0) + return -1; + wpabuf_put_buf(*dst, src); + return 0; +} + + +static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len) +{ + if (!data || !len) + return 0; + if (wpabuf_resize(dst, len) != 0) + return -1; + wpabuf_put_data(*dst, data, len); + return 0; +} + + int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf **beacon_ret, struct wpabuf **proberesp_ret, @@ -49,82 +75,38 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, pos = buf; pos = hostapd_eid_time_adv(hapd, pos); - if (pos != buf) { - if (wpabuf_resize(&beacon, pos - buf) != 0) - goto fail; - wpabuf_put_data(beacon, buf, pos - buf); - } + if (add_buf_data(&beacon, buf, pos - buf) < 0) + goto fail; pos = hostapd_eid_time_zone(hapd, pos); - if (pos != buf) { - if (wpabuf_resize(&proberesp, pos - buf) != 0) - goto fail; - wpabuf_put_data(proberesp, buf, pos - buf); - } + if (add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; pos = buf; pos = hostapd_eid_ext_capab(hapd, pos); - if (pos != buf) { - if (wpabuf_resize(&assocresp, pos - buf) != 0) - goto fail; - wpabuf_put_data(assocresp, buf, pos - buf); - } + if (add_buf_data(&assocresp, buf, pos - buf) < 0) + goto fail; pos = hostapd_eid_interworking(hapd, pos); pos = hostapd_eid_adv_proto(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos); - if (pos != buf) { - if (wpabuf_resize(&beacon, pos - buf) != 0) - goto fail; - wpabuf_put_data(beacon, buf, pos - buf); - - if (wpabuf_resize(&proberesp, pos - buf) != 0) - goto fail; - wpabuf_put_data(proberesp, buf, pos - buf); - } + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; #ifdef CONFIG_FST - if (hapd->iface->fst_ies) { - size_t add = wpabuf_len(hapd->iface->fst_ies); - - if (wpabuf_resize(&beacon, add) < 0) - goto fail; - wpabuf_put_buf(beacon, hapd->iface->fst_ies); - if (wpabuf_resize(&proberesp, add) < 0) - goto fail; - wpabuf_put_buf(proberesp, hapd->iface->fst_ies); - if (wpabuf_resize(&assocresp, add) < 0) - goto fail; - wpabuf_put_buf(assocresp, hapd->iface->fst_ies); - } + if (add_buf(&beacon, hapd->iface->fst_ies) < 0 || + add_buf(&proberesp, hapd->iface->fst_ies) < 0 || + add_buf(&assocresp, hapd->iface->fst_ies) < 0) + goto fail; #endif /* CONFIG_FST */ - if (hapd->wps_beacon_ie) { - if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) < - 0) - goto fail; - wpabuf_put_buf(beacon, hapd->wps_beacon_ie); - } - - if (hapd->wps_probe_resp_ie) { - if (wpabuf_resize(&proberesp, - wpabuf_len(hapd->wps_probe_resp_ie)) < 0) - goto fail; - wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); - } + if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 || + add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0) + goto fail; #ifdef CONFIG_P2P - if (hapd->p2p_beacon_ie) { - if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) < - 0) - goto fail; - wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); - } - - if (hapd->p2p_probe_resp_ie) { - if (wpabuf_resize(&proberesp, - wpabuf_len(hapd->p2p_probe_resp_ie)) < 0) - goto fail; - wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); - } + if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 || + add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0) + goto fail; #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER @@ -148,8 +130,7 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, #ifdef CONFIG_WPS if (hapd->conf->wps_state) { struct wpabuf *a = wps_build_assoc_resp_ie(); - if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) - wpabuf_put_buf(assocresp, a); + add_buf(&assocresp, a); wpabuf_free(a); } #endif /* CONFIG_WPS */ @@ -169,44 +150,36 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, if (hapd->p2p_group) { struct wpabuf *a; a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); - if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) - wpabuf_put_buf(assocresp, a); + add_buf(&assocresp, a); wpabuf_free(a); } #endif /* CONFIG_WIFI_DISPLAY */ #ifdef CONFIG_HS20 - pos = buf; - pos = hostapd_eid_hs20_indication(hapd, pos); - if (pos != buf) { - if (wpabuf_resize(&beacon, pos - buf) != 0) - goto fail; - wpabuf_put_data(beacon, buf, pos - buf); - - if (wpabuf_resize(&proberesp, pos - buf) != 0) - goto fail; - wpabuf_put_data(proberesp, buf, pos - buf); - } + pos = hostapd_eid_hs20_indication(hapd, buf); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; pos = hostapd_eid_osen(hapd, buf); - if (pos != buf) { - if (wpabuf_resize(&beacon, pos - buf) != 0) - goto fail; - wpabuf_put_data(beacon, buf, pos - buf); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; +#endif /* CONFIG_HS20 */ - if (wpabuf_resize(&proberesp, pos - buf) != 0) +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled) { + pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0 || + add_buf_data(&assocresp, buf, pos - buf) < 0) goto fail; - wpabuf_put_data(proberesp, buf, pos - buf); } -#endif /* CONFIG_HS20 */ +#endif /* CONFIG_MBO */ - if (hapd->conf->vendor_elements) { - size_t add = wpabuf_len(hapd->conf->vendor_elements); - if (wpabuf_resize(&beacon, add) == 0) - wpabuf_put_buf(beacon, hapd->conf->vendor_elements); - if (wpabuf_resize(&proberesp, add) == 0) - wpabuf_put_buf(proberesp, hapd->conf->vendor_elements); - } + add_buf(&beacon, hapd->conf->vendor_elements); + add_buf(&proberesp, hapd->conf->vendor_elements); + add_buf(&assocresp, hapd->conf->assocresp_elements); *beacon_ret = beacon; *proberesp_ret = proberesp; @@ -390,7 +363,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, u16 listen_interval, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, - u32 flags, u8 qosinfo, u8 vht_opmode) + u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, + int set) { struct hostapd_sta_add_params params; @@ -412,6 +386,8 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.vht_opmode = vht_opmode; params.flags = hostapd_sta_flags_to_drv(flags); params.qosinfo = qosinfo; + params.support_p2p_ps = supp_p2p_ps; + params.set = set; return hapd->driver->sta_add(hapd->drv_priv, ¶ms); } @@ -468,7 +444,7 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, return -1; return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, bss_ctx, drv_priv, force_ifname, if_addr, - bridge, use_existing); + bridge, use_existing, 1); } @@ -647,16 +623,28 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, int hostapd_drv_send_mlme(struct hostapd_data *hapd, const void *msg, size_t len, int noack) { + if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, + NULL, 0); +} + + +int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd, + const void *msg, size_t len, int noack, + const u16 *csa_offs, size_t csa_offs_len) +{ if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) return 0; - return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0); + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, + csa_offs, csa_offs_len); } int hostapd_drv_sta_deauth(struct hostapd_data *hapd, const u8 *addr, int reason) { - if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) + if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv) return 0; return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, reason); @@ -666,7 +654,7 @@ int hostapd_drv_sta_deauth(struct hostapd_data *hapd, int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, int reason) { - if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) + if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv) return 0; return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, reason); @@ -687,6 +675,36 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *data, size_t len) { + const u8 *bssid; + const u8 wildcard_bssid[ETH_ALEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv) + return 0; + bssid = hapd->own_addr; + if (!is_multicast_ether_addr(dst) && + len > 0 && data[0] == WLAN_ACTION_PUBLIC) { + struct sta_info *sta; + + /* + * Public Action frames to a STA that is not a member of the BSS + * shall use wildcard BSSID value. + */ + sta = ap_get_sta(hapd, dst); + if (!sta || !(sta->flags & WLAN_STA_ASSOC)) + bssid = wildcard_bssid; + } + return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, + hapd->own_addr, bssid, data, len, 0); +} + + +int hostapd_drv_send_action_addr3_ap(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, @@ -736,7 +754,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, 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) + if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv) return 0; return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, qos_map_set_len); @@ -762,6 +780,20 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, } +void hostapd_get_ext_capa(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + + if (!hapd->driver || !hapd->driver->get_ext_capab) + return; + + hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS, + &iface->extended_capa, + &iface->extended_capa_mask, + &iface->extended_capa_len); +} + + int hostapd_drv_do_acs(struct hostapd_data *hapd) { struct drv_acs_params params; |