int ieee802_11_build_ap_params(struct hostapd_data *hapd, struct wpa_driver_ap_params *params) { struct ieee80211_mgmt *head = NULL; u8 *tail = NULL; size_t head_len = 0, tail_len = 0; u8 *resp = NULL; size_t resp_len = 0; #ifdef NEED_AP_MLME u16 capab_info; u8 *pos, *tailpos, *csa_pos; #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); tail_len = BEACON_TAIL_BUF_SIZE; #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) tail_len += wpabuf_len(hapd->wps_beacon_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_beacon_ie) tail_len += wpabuf_len(hapd->p2p_beacon_ie); #endif /* CONFIG_P2P */ #ifdef CONFIG_FST if (hapd->iface->fst_ies) tail_len += wpabuf_len(hapd->iface->fst_ies); #endif /* CONFIG_FST */ if (hapd->conf->vendor_elements) tail_len += wpabuf_len(hapd->conf->vendor_elements); #ifdef CONFIG_IEEE80211AC if (hapd->conf->vendor_vht) { tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + 2 + sizeof(struct ieee80211_vht_operation); } #endif /* CONFIG_IEEE80211AC */ tail_len += hostapd_mbo_ie_len(hapd); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); os_free(tail); return -1; } head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); head->duration = host_to_le16(0); os_memset(head->da, 0xff, ETH_ALEN); os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); head->u.beacon.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ capab_info = hostapd_own_capab_info(hapd); head->u.beacon.capab_info = host_to_le16(capab_info); pos = &head->u.beacon.variable[0]; /* SSID */ *pos++ = WLAN_EID_SSID; if (hapd->conf->ignore_broadcast_ssid == 2) { /* clear the data, but keep the correct length of the SSID */ *pos++ = hapd->conf->ssid.ssid_len; os_memset(pos, 0, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } else if (hapd->conf->ignore_broadcast_ssid) { *pos++ = 0; /* empty SSID */ } else { *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); head_len = pos - (u8 *) head; tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* Power Constraint element */ tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); /* CSA IE */ csa_pos = hostapd_eid_csa(hapd, tailpos); if (csa_pos != tailpos) hapd->cs_c_off_beacon = csa_pos - tail - 1; tailpos = csa_pos; /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos); /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); tailpos = hostapd_eid_bss_load(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* eCSA IE */ csa_pos = hostapd_eid_ecsa(hapd, tailpos); if (csa_pos != tailpos) hapd->cs_c_off_ecsa_beacon = csa_pos - tail - 1; tailpos = csa_pos; tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); #ifdef CONFIG_IEEE80211N /* Secondary Channel Offset element */ /* TODO: The standard doesn't specify a position for this element. */ tailpos = hostapd_eid_secondary_channel(hapd, tailpos); tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); /* * TODO: Time Advertisement element should only be included in some * DTIM Beacon frames. */ tailpos = hostapd_eid_time_adv(hapd, tailpos); tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); #ifdef CONFIG_FST if (hapd->iface->fst_ies) { os_memcpy(tailpos, wpabuf_head(hapd->iface->fst_ies), wpabuf_len(hapd->iface->fst_ies)); tailpos += wpabuf_len(hapd->iface->fst_ies); } #endif /* CONFIG_FST */ #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { tailpos = hostapd_eid_vht_capabilities(hapd, tailpos); tailpos = hostapd_eid_vht_operation(hapd, tailpos); tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); } if (hapd->conf->vendor_vht) tailpos = hostapd_eid_vendor_vht(hapd, tailpos); #endif /* CONFIG_IEEE80211AC */ /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), wpabuf_len(hapd->wps_beacon_ie)); tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), wpabuf_len(hapd->p2p_beacon_ie)); tailpos += wpabuf_len(hapd->p2p_beacon_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) tailpos = hostapd_eid_p2p_manage(hapd, tailpos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 tailpos = hostapd_eid_hs20_indication(hapd, tailpos); tailpos = hostapd_eid_osen(hapd, tailpos); #endif /* CONFIG_HS20 */ tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); tailpos += wpabuf_len(hapd->conf->vendor_elements); } tail_len = tailpos > tail ? tailpos - tail : 0; resp = hostapd_probe_resp_offloads(hapd, &resp_len); #endif /* NEED_AP_MLME */ os_memset(params, 0, sizeof(*params)); params->head = (u8 *) head; params->head_len = head_len; params->tail = tail; params->tail_len = tail_len; params->proberesp = resp; params->proberesp_len = resp_len; params->dtim_period = hapd->conf->dtim_period; params->beacon_int = hapd->iconf->beacon_int; params->basic_rates = hapd->iface->basic_rates; params->ssid = hapd->conf->ssid.ssid; params->ssid_len = hapd->conf->ssid.ssid_len; if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == (WPA_PROTO_WPA | WPA_PROTO_RSN)) params->pairwise_ciphers = hapd->conf->wpa_pairwise | hapd->conf->rsn_pairwise; else if (hapd->conf->wpa & WPA_PROTO_RSN) params->pairwise_ciphers = hapd->conf->rsn_pairwise; else if (hapd->conf->wpa & WPA_PROTO_WPA) params->pairwise_ciphers = hapd->conf->wpa_pairwise; params->group_cipher = hapd->conf->wpa_group; params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; params->auth_algs = hapd->conf->auth_algs; params->wpa_version = hapd->conf->wpa; params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); switch (hapd->conf->ignore_broadcast_ssid) { case 0: params->hide_ssid = NO_SSID_HIDING; break; case 1: params->hide_ssid = HIDDEN_SSID_ZERO_LEN; break; case 2: params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; break; } params->isolate = hapd->conf->isolate; params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK; #ifdef NEED_AP_MLME params->cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); params->preamble = hapd->iface->num_sta_no_short_preamble == 0 && hapd->iconf->preamble == SHORT_PREAMBLE; if (hapd->iface->current_mode && hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) params->short_slot_time = hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; else params->short_slot_time = -1; if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) params->ht_opmode = -1; else params->ht_opmode = hapd->iface->ht_op_mode; #endif /* NEED_AP_MLME */ params->interworking = hapd->conf->interworking; if (hapd->conf->interworking && !is_zero_ether_addr(hapd->conf->hessid)) params->hessid = hapd->conf->hessid; params->access_network_type = hapd->conf->access_network_type; params->ap_max_inactivity = hapd->conf->ap_max_inactivity; #ifdef CONFIG_P2P params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow; #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 params->disable_dgaf = hapd->conf->disable_dgaf; if (hapd->conf->osen) { params->privacy = 1; params->osen = 1; } #endif /* CONFIG_HS20 */ params->pbss = hapd->conf->pbss; return 0; }
void ieee802_11_set_beacon(struct hostapd_data *hapd) { struct ieee80211_mgmt *head = NULL; u8 *tail = NULL; size_t head_len = 0, tail_len = 0; u8 *resp = NULL; size_t resp_len = 0; struct wpa_driver_ap_params params; struct wpabuf *beacon, *proberesp, *assocresp; #ifdef NEED_AP_MLME u16 capab_info; u8 *pos, *tailpos; #endif /* NEED_AP_MLME */ hapd->beacon_set_done = 1; #ifdef NEED_AP_MLME #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); tail_len = BEACON_TAIL_BUF_SIZE; #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) tail_len += wpabuf_len(hapd->wps_beacon_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_beacon_ie) tail_len += wpabuf_len(hapd->p2p_beacon_ie); #endif /* CONFIG_P2P */ if (hapd->conf->vendor_elements) tail_len += wpabuf_len(hapd->conf->vendor_elements); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); os_free(tail); return; } head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); head->duration = host_to_le16(0); os_memset(head->da, 0xff, ETH_ALEN); os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); head->u.beacon.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ capab_info = hostapd_own_capab_info(hapd, NULL, 0); head->u.beacon.capab_info = host_to_le16(capab_info); pos = &head->u.beacon.variable[0]; /* SSID */ //Tymon added for load-balancing if(set_beacon_req){ if( (hapd->num_sta >= hapd->conf->max_num_sta) && (hapd->conf->ignore_broadcast_ssid == 0) ) hapd->conf->ignore_broadcast_ssid = 1; else if( hapd->num_sta < hapd->conf->max_num_sta && (hapd->conf->ignore_broadcast_ssid) && set_beacon_req ) hapd->conf->ignore_broadcast_ssid = 0; set_beacon_req = 0; } // *pos++ = WLAN_EID_SSID; if (hapd->conf->ignore_broadcast_ssid == 2) { /* clear the data, but keep the correct length of the SSID */ *pos++ = hapd->conf->ssid.ssid_len; os_memset(pos, 0, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } else if (hapd->conf->ignore_broadcast_ssid) { *pos++ = 0; /* empty SSID */ } else { *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); head_len = pos - (u8 *) head; tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos); /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); #ifdef CONFIG_IEEE80211N tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); /* * TODO: Time Advertisement element should only be included in some * DTIM Beacon frames. */ tailpos = hostapd_eid_time_adv(hapd, tailpos); tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); #ifdef CONFIG_IEEE80211AC tailpos = hostapd_eid_vht_capabilities(hapd, tailpos); tailpos = hostapd_eid_vht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211AC */ /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), wpabuf_len(hapd->wps_beacon_ie)); tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), wpabuf_len(hapd->p2p_beacon_ie)); tailpos += wpabuf_len(hapd->p2p_beacon_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) tailpos = hostapd_eid_p2p_manage(hapd, tailpos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 tailpos = hostapd_eid_hs20_indication(hapd, tailpos); #endif /* CONFIG_HS20 */ if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); tailpos += wpabuf_len(hapd->conf->vendor_elements); } tail_len = tailpos > tail ? tailpos - tail : 0; resp = hostapd_probe_resp_offloads(hapd, &resp_len); #endif /* NEED_AP_MLME */ os_memset(¶ms, 0, sizeof(params)); params.head = (u8 *) head; params.head_len = head_len; params.tail = tail; params.tail_len = tail_len; params.proberesp = resp; params.proberesp_len = resp_len; params.dtim_period = hapd->conf->dtim_period; params.beacon_int = hapd->iconf->beacon_int; params.basic_rates = hapd->iface->basic_rates; params.ssid = hapd->conf->ssid.ssid; params.ssid_len = hapd->conf->ssid.ssid_len; params.pairwise_ciphers = hapd->conf->rsn_pairwise ? hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise; params.group_cipher = hapd->conf->wpa_group; params.key_mgmt_suites = hapd->conf->wpa_key_mgmt; params.auth_algs = hapd->conf->auth_algs; params.wpa_version = hapd->conf->wpa; params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); switch (hapd->conf->ignore_broadcast_ssid) { case 0: params.hide_ssid = NO_SSID_HIDING; break; case 1: params.hide_ssid = HIDDEN_SSID_ZERO_LEN; break; case 2: params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; break; } hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp); params.beacon_ies = beacon; params.proberesp_ies = proberesp; params.assocresp_ies = assocresp; params.isolate = hapd->conf->isolate; #ifdef NEED_AP_MLME params.cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); params.preamble = hapd->iface->num_sta_no_short_preamble == 0 && hapd->iconf->preamble == SHORT_PREAMBLE; if (hapd->iface->current_mode && hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) params.short_slot_time = hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; else params.short_slot_time = -1; if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) params.ht_opmode = -1; else params.ht_opmode = hapd->iface->ht_op_mode; #endif /* NEED_AP_MLME */ params.interworking = hapd->conf->interworking; if (hapd->conf->interworking && !is_zero_ether_addr(hapd->conf->hessid)) params.hessid = hapd->conf->hessid; params.access_network_type = hapd->conf->access_network_type; params.ap_max_inactivity = hapd->conf->ap_max_inactivity; #ifdef CONFIG_HS20 params.disable_dgaf = hapd->conf->disable_dgaf; #endif /* CONFIG_HS20 */ if (hostapd_drv_set_ap(hapd, ¶ms)) wpa_printf(MSG_ERROR, "Failed to set beacon parameters"); hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); os_free(tail); os_free(head); os_free(resp); }