int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf **beacon_ret, struct wpabuf **proberesp_ret, struct wpabuf **assocresp_ret) { struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; u8 buf[200], *pos; *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; 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); } 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); } 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); } 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 (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); } #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); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { if (wpabuf_resize(&beacon, 100) == 0) { u8 *start, *p; start = wpabuf_put(beacon, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(beacon, p - start); } if (wpabuf_resize(&proberesp, 100) == 0) { u8 *start, *p; start = wpabuf_put(proberesp, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(proberesp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_WPS2 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); wpabuf_free(a); } #endif /* CONFIG_WPS2 */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { if (wpabuf_resize(&assocresp, 100) == 0) { u8 *start, *p; start = wpabuf_put(assocresp, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(assocresp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_WIFI_DISPLAY 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); 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); } #endif /* CONFIG_HS20 */ *beacon_ret = beacon; *proberesp_ret = proberesp; *assocresp_ret = assocresp; return 0; fail: wpabuf_free(beacon); wpabuf_free(proberesp); wpabuf_free(assocresp); return -1; }
static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) { struct wpabuf *beacon, *proberesp, *assocresp = NULL; int ret; if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) return 0; beacon = hapd->wps_beacon_ie; proberesp = hapd->wps_probe_resp_ie; #ifdef CONFIG_P2P if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL) beacon = NULL; else { beacon = wpabuf_alloc((hapd->wps_beacon_ie ? wpabuf_len(hapd->wps_beacon_ie) : 0) + (hapd->p2p_beacon_ie ? wpabuf_len(hapd->p2p_beacon_ie) : 0)); if (beacon == NULL) return -1; if (hapd->wps_beacon_ie) wpabuf_put_buf(beacon, hapd->wps_beacon_ie); if (hapd->p2p_beacon_ie) wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); } if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL) proberesp = NULL; else { proberesp = wpabuf_alloc( (hapd->wps_probe_resp_ie ? wpabuf_len(hapd->wps_probe_resp_ie) : 0) + (hapd->p2p_probe_resp_ie ? wpabuf_len(hapd->p2p_probe_resp_ie) : 0)); if (proberesp == NULL) { wpabuf_free(beacon); return -1; } if (hapd->wps_probe_resp_ie) wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); if (hapd->p2p_probe_resp_ie) wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_WPS2 if (hapd->conf->wps_state) assocresp = wps_build_assoc_resp_ie(); #endif /* CONFIG_WPS2 */ ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, assocresp); #ifdef CONFIG_P2P wpabuf_free(beacon); wpabuf_free(proberesp); #endif /* CONFIG_P2P */ wpabuf_free(assocresp); return ret; }
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) { struct wpabuf *beacon, *proberesp, *assocresp = NULL; int ret; if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) return 0; beacon = hapd->wps_beacon_ie; proberesp = hapd->wps_probe_resp_ie; #ifdef CONFIG_P2P if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL) beacon = NULL; else { beacon = wpabuf_alloc((hapd->wps_beacon_ie ? wpabuf_len(hapd->wps_beacon_ie) : 0) + (hapd->p2p_beacon_ie ? wpabuf_len(hapd->p2p_beacon_ie) : 0)); if (beacon == NULL) return -1; if (hapd->wps_beacon_ie) wpabuf_put_buf(beacon, hapd->wps_beacon_ie); if (hapd->p2p_beacon_ie) wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); } if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL) proberesp = NULL; else { proberesp = wpabuf_alloc( (hapd->wps_probe_resp_ie ? wpabuf_len(hapd->wps_probe_resp_ie) : 0) + (hapd->p2p_probe_resp_ie ? wpabuf_len(hapd->p2p_probe_resp_ie) : 0)); if (proberesp == NULL) { wpabuf_free(beacon); return -1; } if (hapd->wps_probe_resp_ie) wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie); if (hapd->p2p_probe_resp_ie) wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { struct wpabuf *a; a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0)); if (a) { u8 *start, *p; if (beacon) wpabuf_put_buf(a, beacon); if (beacon != hapd->wps_beacon_ie) wpabuf_free(beacon); start = wpabuf_put(a, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(a, p - start); beacon = a; } a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) : 0)); if (a) { u8 *start, *p; if (proberesp) wpabuf_put_buf(a, proberesp); if (proberesp != hapd->wps_probe_resp_ie) wpabuf_free(proberesp); start = wpabuf_put(a, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(a, p - start); proberesp = a; } } #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_WPS2 if (hapd->conf->wps_state) assocresp = wps_build_assoc_resp_ie(); #endif /* CONFIG_WPS2 */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { struct wpabuf *a; a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) : 0)); if (a) { u8 *start, *p; start = wpabuf_put(a, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(a, p - start); if (assocresp) { wpabuf_put_buf(a, assocresp); wpabuf_free(assocresp); } assocresp = a; } } #endif /* CONFIG_P2P_MANAGER */ ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, assocresp); if (beacon != hapd->wps_beacon_ie) wpabuf_free(beacon); if (proberesp != hapd->wps_probe_resp_ie) wpabuf_free(proberesp); wpabuf_free(assocresp); return ret; }
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf **beacon_ret, struct wpabuf **proberesp_ret, struct wpabuf **assocresp_ret) { struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; u8 buf[200], *pos; *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; pos = buf; pos = hostapd_eid_time_adv(hapd, pos); if (add_buf_data(&beacon, buf, pos - buf) < 0) goto fail; pos = hostapd_eid_time_zone(hapd, pos); if (add_buf_data(&proberesp, buf, pos - buf) < 0) goto fail; pos = buf; pos = hostapd_eid_ext_capab(hapd, pos); 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 (add_buf_data(&beacon, buf, pos - buf) < 0 || add_buf_data(&proberesp, buf, pos - buf) < 0) goto fail; #ifdef CONFIG_FST 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 */ #ifdef CONFIG_FILS pos = hostapd_eid_fils_indic(hapd, buf, 0); if (add_buf_data(&beacon, buf, pos - buf) < 0 || add_buf_data(&proberesp, buf, pos - buf) < 0) goto fail; #endif /* CONFIG_FILS */ if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 || add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0) goto fail; #ifdef CONFIG_P2P 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 if (hapd->conf->p2p & P2P_MANAGE) { if (wpabuf_resize(&beacon, 100) == 0) { u8 *start, *p; start = wpabuf_put(beacon, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(beacon, p - start); } if (wpabuf_resize(&proberesp, 100) == 0) { u8 *start, *p; start = wpabuf_put(proberesp, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(proberesp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_WPS if (hapd->conf->wps_state) { struct wpabuf *a = wps_build_assoc_resp_ie(); add_buf(&assocresp, a); wpabuf_free(a); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P_MANAGER if (hapd->conf->p2p & P2P_MANAGE) { if (wpabuf_resize(&assocresp, 100) == 0) { u8 *start, *p; start = wpabuf_put(assocresp, 0); p = hostapd_eid_p2p_manage(hapd, start); wpabuf_put(assocresp, p - start); } } #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_WIFI_DISPLAY if (hapd->p2p_group) { struct wpabuf *a; a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); add_buf(&assocresp, a); wpabuf_free(a); } #endif /* CONFIG_WIFI_DISPLAY */ #ifdef CONFIG_HS20 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 (add_buf_data(&beacon, buf, pos - buf) < 0 || add_buf_data(&proberesp, buf, pos - buf) < 0) goto fail; #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled || hapd->enable_oce) { 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; } #endif /* CONFIG_MBO */ 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; *assocresp_ret = assocresp; return 0; fail: wpabuf_free(beacon); wpabuf_free(proberesp); wpabuf_free(assocresp); return -1; }
static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, u16 status_code, int reassoc, const u8 *ies, size_t ies_len) { int send_len; u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; struct ieee80211_mgmt *reply; u8 *p; os_memset(buf, 0, sizeof(buf)); reply = (struct ieee80211_mgmt *) buf; reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : WLAN_FC_STYPE_ASSOC_RESP)); os_memcpy(reply->da, sta->addr, ETH_ALEN); os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN); send_len = IEEE80211_HDRLEN; send_len += sizeof(reply->u.assoc_resp); reply->u.assoc_resp.capab_info = host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); reply->u.assoc_resp.status_code = host_to_le16(status_code); reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) | BIT(14) | BIT(15)); /* Supported rates */ p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); /* Extended supported rates */ p = hostapd_eid_ext_supp_rates(hapd, p); #ifdef CONFIG_IEEE80211R if (status_code == WLAN_STATUS_SUCCESS) { /* IEEE 802.11r: Mobility Domain Information, Fast BSS * Transition Information, RSN, [RIC Response] */ p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, buf + sizeof(buf) - p, sta->auth_alg, ies, ies_len); } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) p = hostapd_eid_assoc_comeback_time(hapd, sta, p); #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211N p = hostapd_eid_ht_capabilities(hapd, p); p = hostapd_eid_ht_operation(hapd, p); #endif /* CONFIG_IEEE80211N */ if (sta->flags & WLAN_STA_WMM) p = hostapd_eid_wmm(hapd, p); #ifdef CONFIG_WPS if (sta->flags & WLAN_STA_WPS) { struct wpabuf *wps = wps_build_assoc_resp_ie(); if (wps) { os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); p += wpabuf_len(wps); wpabuf_free(wps); } } #endif /* CONFIG_WPS */ send_len += p - reply->u.assoc_resp.variable; if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0) wpa_printf(MSG_INFO, "Failed to send assoc resp: %s", strerror(errno)); }