X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fap%2Fbeacon.c;h=38182aebebcc5962e1238a7d57cff0314bc23f38;hb=04059ab84458f43dda9130e4fff745b268424b99;hp=ea6b009c4e780e3756c832100060bc4c139fb116;hpb=244d4d8bff1a52f8f8357d2be615ca1778576b60;p=mech_eap.git diff --git a/src/ap/beacon.c b/src/ap/beacon.c index ea6b009..38182ae 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -29,6 +29,7 @@ #include "beacon.h" #include "hs20.h" #include "dfs.h" +#include "taxonomy.h" #ifdef NEED_AP_MLME @@ -36,18 +37,21 @@ static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, size_t len) { - if (!hapd->conf->radio_measurements || len < 2 + 4) + size_t i; + + for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) { + if (hapd->conf->radio_measurements[i]) + break; + } + + if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN) return eid; *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; - *eid++ = 5; - *eid++ = (hapd->conf->radio_measurements & BIT(0)) ? - WLAN_RRM_CAPS_NEIGHBOR_REPORT : 0x00; - *eid++ = 0x00; - *eid++ = 0x00; - *eid++ = 0x00; - *eid++ = 0x00; - return eid; + *eid++ = RRM_CAPABILITIES_IE_LEN; + os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN); + + return eid + RRM_CAPABILITIES_IE_LEN; } @@ -297,6 +301,11 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid) { +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iface->cs_oper_class && hapd->iconf->ecsa_ie_only) + return eid; +#endif /* CONFIG_TESTING_OPTIONS */ + if (!hapd->cs_freq_params.channel) return eid; @@ -310,49 +319,47 @@ static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid) } -static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) +static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid) { - u8 sec_ch; - - if (!hapd->cs_freq_params.sec_channel_offset) - return eid; - - if (hapd->cs_freq_params.sec_channel_offset == -1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW; - else if (hapd->cs_freq_params.sec_channel_offset == 1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE; - else + if (!hapd->cs_freq_params.channel || !hapd->iface->cs_oper_class) return eid; - *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; - *eid++ = 1; - *eid++ = sec_ch; + *eid++ = WLAN_EID_EXT_CHANSWITCH_ANN; + *eid++ = 4; + *eid++ = hapd->cs_block_tx; + *eid++ = hapd->iface->cs_oper_class; + *eid++ = hapd->cs_freq_params.channel; + *eid++ = hapd->cs_count; return eid; } -static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos, - u8 *start, unsigned int *csa_counter_off) +static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid) { - u8 *old_pos = pos; + u8 op_class, channel; - if (!csa_counter_off) - return pos; + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || + !hapd->iface->freq) + return eid; - *csa_counter_off = 0; - pos = hostapd_eid_csa(hapd, pos); + if (ieee80211_freq_to_channel_ext(hapd->iface->freq, + hapd->iconf->secondary_channel, + hapd->iconf->vht_oper_chwidth, + &op_class, &channel) == + NUM_HOSTAPD_MODES) + return eid; - if (pos != old_pos) { - /* save an offset to the counter - should be last byte */ - *csa_counter_off = pos - start - 1; - pos = hostapd_eid_secondary_channel(hapd, pos); -#ifdef CONFIG_IEEE80211AC - pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); -#endif /* CONFIG_IEEE80211AC */ - } + *eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES; + *eid++ = 2; - return pos; + /* Current Operating Class */ + *eid++ = op_class; + + /* TODO: Advertise all the supported operating classes */ + *eid++ = 0; + + return eid; } @@ -361,7 +368,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, int is_p2p, size_t *resp_len) { struct ieee80211_mgmt *resp; - u8 *pos, *epos; + u8 *pos, *epos, *csa_pos; size_t buflen; #define MAX_PROBERESP_LEN 768 @@ -384,6 +391,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + 2 + sizeof(struct ieee80211_vht_operation); } + + buflen += hostapd_mbo_ie_len(hapd); + resp = os_zalloc(buflen); if (resp == NULL) return NULL; @@ -421,6 +431,12 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, /* Power Constraint element */ pos = hostapd_eid_pwr_constraint(hapd, pos); + /* CSA IE */ + csa_pos = hostapd_eid_csa(hapd, pos); + if (csa_pos != pos) + hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1; + pos = csa_pos; + /* ERP Information element */ pos = hostapd_eid_erp_info(hapd, pos); @@ -434,7 +450,19 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); + /* eCSA IE */ + csa_pos = hostapd_eid_ecsa(hapd, pos); + if (csa_pos != pos) + hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1; + pos = csa_pos; + + pos = hostapd_eid_supported_op_classes(hapd, pos); + #ifdef CONFIG_IEEE80211N + /* Secondary Channel Offset element */ + /* TODO: The standard doesn't specify a position for this element. */ + pos = hostapd_eid_secondary_channel(hapd, pos); + pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); #endif /* CONFIG_IEEE80211N */ @@ -448,9 +476,6 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_adv_proto(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos); - pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp, - &hapd->cs_c_off_proberesp); - #ifdef CONFIG_FST if (hapd->iface->fst_ies) { os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies), @@ -461,8 +486,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { - pos = hostapd_eid_vht_capabilities(hapd, pos); + pos = hostapd_eid_vht_capabilities(hapd, pos, 0); pos = hostapd_eid_vht_operation(hapd, pos); + pos = hostapd_eid_txpower_envelope(hapd, pos); + pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); } if (hapd->conf->vendor_vht) pos = hostapd_eid_vendor_vht(hapd, pos); @@ -498,6 +525,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_osen(hapd, pos); #endif /* CONFIG_HS20 */ + pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); + if (hapd->conf->vendor_elements) { os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); @@ -534,8 +563,8 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd, pos = ssid_list; end = ssid_list + ssid_list_len; - while (pos + 1 <= end) { - if (pos + 2 + pos[1] > end) + while (end - pos >= 1) { + if (2 + pos[1] > end - pos) break; if (pos[1] == 0) wildcard = 1; @@ -604,6 +633,8 @@ void sta_track_add(struct hostapd_iface *iface, const u8 *addr) /* Add a new entry */ info = os_zalloc(sizeof(*info)); + if (info == NULL) + return; os_memcpy(info->addr, addr, ETH_ALEN); os_get_reltime(&info->last_seen); @@ -656,13 +687,16 @@ void handle_probe_req(struct hostapd_data *hapd, size_t i, resp_len; int noack; enum ssid_match_result res; + int ret; + u16 csa_offs[2]; + size_t csa_offs_len; - ie = mgmt->u.probe_req.variable; - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) + if (len < IEEE80211_HDRLEN) return; + ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN; if (hapd->iconf->track_sta_max_num) sta_track_add(hapd->iface, mgmt->sa); - ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); + ie_len = len - IEEE80211_HDRLEN; for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, @@ -708,7 +742,7 @@ void handle_probe_req(struct hostapd_data *hapd, } #ifdef CONFIG_P2P - if (hapd->p2p && elems.wps_ie) { + if (hapd->p2p && hapd->p2p_group && elems.wps_ie) { struct wpabuf *wps; wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { @@ -721,7 +755,7 @@ void handle_probe_req(struct hostapd_data *hapd, wpabuf_free(wps); } - if (hapd->p2p && elems.p2p) { + if (hapd->p2p && hapd->p2p_group && elems.p2p) { struct wpabuf *p2p; p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE); if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) { @@ -751,6 +785,14 @@ void handle_probe_req(struct hostapd_data *hapd, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_TAXONOMY + { + struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); + if (sta) + taxonomy_sta_info_probe_req(hapd, sta, ie, ie_len); + } +#endif /* CONFIG_TAXONOMY */ + res = ssid_match(hapd, elems.ssid, elems.ssid_len, elems.ssid_list, elems.ssid_list_len); if (res == NO_SSID_MATCH) { @@ -822,6 +864,17 @@ void handle_probe_req(struct hostapd_data *hapd, return; } + if (hapd->conf->no_probe_resp_if_max_sta && + is_multicast_ether_addr(mgmt->da) && + is_multicast_ether_addr(mgmt->bssid) && + hapd->num_sta >= hapd->conf->max_num_sta && + !ap_get_sta(hapd, mgmt->sa)) { + wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR + " since no room for additional STA", + hapd->conf->iface, MAC2STR(mgmt->sa)); + return; + } + #ifdef CONFIG_TESTING_OPTIONS if (hapd->iconf->ignore_probe_probability > 0.0 && drand48() < hapd->iconf->ignore_probe_probability) { @@ -844,7 +897,22 @@ void handle_probe_req(struct hostapd_data *hapd, noack = !!(res == WILDCARD_SSID_MATCH && is_broadcast_ether_addr(mgmt->da)); - if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0) + csa_offs_len = 0; + if (hapd->csa_in_progress) { + if (hapd->cs_c_off_proberesp) + csa_offs[csa_offs_len++] = + hapd->cs_c_off_proberesp; + + if (hapd->cs_c_off_ecsa_proberesp) + csa_offs[csa_offs_len++] = + hapd->cs_c_off_ecsa_proberesp; + } + + ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack, + csa_offs_len ? csa_offs : NULL, + csa_offs_len); + + if (ret < 0) wpa_printf(MSG_INFO, "handle_probe_req: send failed"); os_free(resp); @@ -903,7 +971,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, size_t resp_len = 0; #ifdef NEED_AP_MLME u16 capab_info; - u8 *pos, *tailpos; + u8 *pos, *tailpos, *csa_pos; #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 @@ -931,6 +999,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, } #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"); @@ -984,6 +1054,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, /* 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); @@ -1001,7 +1077,19 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, 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 */ @@ -1017,8 +1105,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); - tailpos = hostapd_add_csa_elems(hapd, tailpos, tail, - &hapd->cs_c_off_beacon); #ifdef CONFIG_FST if (hapd->iface->fst_ies) { @@ -1030,8 +1116,10 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { - tailpos = hostapd_eid_vht_capabilities(hapd, tailpos); + tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0); 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); @@ -1066,6 +1154,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, 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)); @@ -1150,6 +1240,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, params->osen = 1; } #endif /* CONFIG_HS20 */ + params->pbss = hapd->conf->pbss; return 0; }