LCOV - code coverage report
Current view: top level - src/ap - beacon.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 578 631 91.6 %
Date: 2015-09-27 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
       3             :  * Copyright (c) 2002-2004, Instant802 Networks, Inc.
       4             :  * Copyright (c) 2005-2006, Devicescape Software, Inc.
       5             :  * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "utils/includes.h"
      12             : 
      13             : #ifndef CONFIG_NATIVE_WINDOWS
      14             : 
      15             : #include "utils/common.h"
      16             : #include "common/ieee802_11_defs.h"
      17             : #include "common/ieee802_11_common.h"
      18             : #include "common/hw_features_common.h"
      19             : #include "wps/wps_defs.h"
      20             : #include "p2p/p2p.h"
      21             : #include "hostapd.h"
      22             : #include "ieee802_11.h"
      23             : #include "wpa_auth.h"
      24             : #include "wmm.h"
      25             : #include "ap_config.h"
      26             : #include "sta_info.h"
      27             : #include "p2p_hostapd.h"
      28             : #include "ap_drv_ops.h"
      29             : #include "beacon.h"
      30             : #include "hs20.h"
      31             : #include "dfs.h"
      32             : 
      33             : 
      34             : #ifdef NEED_AP_MLME
      35             : 
      36        8552 : static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
      37             :                                          size_t len)
      38             : {
      39        8552 :         if (!hapd->conf->radio_measurements || len < 2 + 4)
      40        8550 :                 return eid;
      41             : 
      42           2 :         *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
      43           2 :         *eid++ = 5;
      44           2 :         *eid++ = (hapd->conf->radio_measurements & BIT(0)) ?
      45             :                 WLAN_RRM_CAPS_NEIGHBOR_REPORT : 0x00;
      46           2 :         *eid++ = 0x00;
      47           2 :         *eid++ = 0x00;
      48           2 :         *eid++ = 0x00;
      49           2 :         *eid++ = 0x00;
      50           2 :         return eid;
      51             : }
      52             : 
      53             : 
      54        8552 : static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
      55             : {
      56        8552 :         if (len < 2 + 5)
      57           0 :                 return eid;
      58             : 
      59             : #ifdef CONFIG_TESTING_OPTIONS
      60        8552 :         if (hapd->conf->bss_load_test_set) {
      61          11 :                 *eid++ = WLAN_EID_BSS_LOAD;
      62          11 :                 *eid++ = 5;
      63          11 :                 os_memcpy(eid, hapd->conf->bss_load_test, 5);
      64          11 :                 eid += 5;
      65          11 :                 return eid;
      66             :         }
      67             : #endif /* CONFIG_TESTING_OPTIONS */
      68        8541 :         if (hapd->conf->bss_load_update_period) {
      69           7 :                 *eid++ = WLAN_EID_BSS_LOAD;
      70           7 :                 *eid++ = 5;
      71           7 :                 WPA_PUT_LE16(eid, hapd->num_sta);
      72           7 :                 eid += 2;
      73           7 :                 *eid++ = hapd->iface->channel_utilization;
      74           7 :                 WPA_PUT_LE16(eid, 0); /* no available admission capabity */
      75           7 :                 eid += 2;
      76             :         }
      77        8541 :         return eid;
      78             : }
      79             : 
      80             : 
      81       12256 : static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
      82             : {
      83       12256 :         u8 erp = 0;
      84             : 
      85       24500 :         if (hapd->iface->current_mode == NULL ||
      86       12244 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
      87         577 :                 return 0;
      88             : 
      89       11679 :         if (hapd->iface->olbc)
      90           2 :                 erp |= ERP_INFO_USE_PROTECTION;
      91       11679 :         if (hapd->iface->num_sta_non_erp > 0) {
      92           0 :                 erp |= ERP_INFO_NON_ERP_PRESENT |
      93             :                         ERP_INFO_USE_PROTECTION;
      94             :         }
      95       23358 :         if (hapd->iface->num_sta_no_short_preamble > 0 ||
      96       11679 :             hapd->iconf->preamble == LONG_PREAMBLE)
      97       11676 :                 erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
      98             : 
      99       11679 :         return erp;
     100             : }
     101             : 
     102             : 
     103        8552 : static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
     104             : {
     105        8552 :         *eid++ = WLAN_EID_DS_PARAMS;
     106        8552 :         *eid++ = 1;
     107        8552 :         *eid++ = hapd->iconf->channel;
     108        8552 :         return eid;
     109             : }
     110             : 
     111             : 
     112        8552 : static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
     113             : {
     114       17092 :         if (hapd->iface->current_mode == NULL ||
     115        8540 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
     116         796 :                 return eid;
     117             : 
     118             :         /* Set NonERP_present and use_protection bits if there
     119             :          * are any associated NonERP stations. */
     120             :         /* TODO: use_protection bit can be set to zero even if
     121             :          * there are NonERP stations present. This optimization
     122             :          * might be useful if NonERP stations are "quiet".
     123             :          * See 802.11g/D6 E-1 for recommended practice.
     124             :          * In addition, Non ERP present might be set, if AP detects Non ERP
     125             :          * operation on other APs. */
     126             : 
     127             :         /* Add ERP Information element */
     128        7756 :         *eid++ = WLAN_EID_ERP_INFO;
     129        7756 :         *eid++ = 1;
     130        7756 :         *eid++ = ieee802_11_erp_info(hapd);
     131             : 
     132        7756 :         return eid;
     133             : }
     134             : 
     135             : 
     136        8552 : static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid)
     137             : {
     138        8552 :         u8 *pos = eid;
     139        8552 :         u8 local_pwr_constraint = 0;
     140             :         int dfs;
     141             : 
     142       17092 :         if (hapd->iface->current_mode == NULL ||
     143        8540 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
     144        7792 :                 return eid;
     145             : 
     146             :         /* Let host drivers add this IE if DFS support is offloaded */
     147         760 :         if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
     148           0 :                 return eid;
     149             : 
     150             :         /*
     151             :          * There is no DFS support and power constraint was not directly
     152             :          * requested by config option.
     153             :          */
     154        1490 :         if (!hapd->iconf->ieee80211h &&
     155         730 :             hapd->iconf->local_pwr_constraint == -1)
     156         728 :                 return eid;
     157             : 
     158             :         /* Check if DFS is required by regulatory. */
     159          32 :         dfs = hostapd_is_dfs_required(hapd->iface);
     160          32 :         if (dfs < 0) {
     161           0 :                 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
     162             :                            dfs);
     163           0 :                 dfs = 0;
     164             :         }
     165             : 
     166          32 :         if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1)
     167          14 :                 return eid;
     168             : 
     169             :         /*
     170             :          * ieee80211h (DFS) is enabled so Power Constraint element shall
     171             :          * be added when running on DFS channel whenever local_pwr_constraint
     172             :          * is configured or not. In order to meet regulations when TPC is not
     173             :          * implemented using a transmit power that is below the legal maximum
     174             :          * (including any mitigation factor) should help. In this case,
     175             :          * indicate 3 dB below maximum allowed transmit power.
     176             :          */
     177          18 :         if (hapd->iconf->local_pwr_constraint == -1)
     178          16 :                 local_pwr_constraint = 3;
     179             : 
     180             :         /*
     181             :          * A STA that is not an AP shall use a transmit power less than or
     182             :          * equal to the local maximum transmit power level for the channel.
     183             :          * The local maximum transmit power can be calculated from the formula:
     184             :          * local max TX pwr = max TX pwr - local pwr constraint
     185             :          * Where max TX pwr is maximum transmit power level specified for
     186             :          * channel in Country element and local pwr constraint is specified
     187             :          * for channel in this Power Constraint element.
     188             :          */
     189             : 
     190             :         /* Element ID */
     191          18 :         *pos++ = WLAN_EID_PWR_CONSTRAINT;
     192             :         /* Length */
     193          18 :         *pos++ = 1;
     194             :         /* Local Power Constraint */
     195          18 :         if (local_pwr_constraint)
     196          16 :                 *pos++ = local_pwr_constraint;
     197             :         else
     198           2 :                 *pos++ = hapd->iconf->local_pwr_constraint;
     199             : 
     200          18 :         return pos;
     201             : }
     202             : 
     203             : 
     204         105 : static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
     205             :                                     struct hostapd_channel_data *start,
     206             :                                     struct hostapd_channel_data *prev)
     207             : {
     208         105 :         if (end - pos < 3)
     209           0 :                 return pos;
     210             : 
     211             :         /* first channel number */
     212         105 :         *pos++ = start->chan;
     213             :         /* number of channels */
     214         105 :         *pos++ = (prev->chan - start->chan) / chan_spacing + 1;
     215             :         /* maximum transmit power level */
     216         105 :         *pos++ = start->max_tx_power;
     217             : 
     218         105 :         return pos;
     219             : }
     220             : 
     221             : 
     222        8552 : static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
     223             :                                 int max_len)
     224             : {
     225        8552 :         u8 *pos = eid;
     226        8552 :         u8 *end = eid + max_len;
     227             :         int i;
     228             :         struct hostapd_hw_modes *mode;
     229             :         struct hostapd_channel_data *start, *prev;
     230        8552 :         int chan_spacing = 1;
     231             : 
     232        8623 :         if (!hapd->iconf->ieee80211d || max_len < 6 ||
     233          71 :             hapd->iface->current_mode == NULL)
     234        8481 :                 return eid;
     235             : 
     236          71 :         *pos++ = WLAN_EID_COUNTRY;
     237          71 :         pos++; /* length will be set later */
     238          71 :         os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
     239          71 :         pos += 3;
     240             : 
     241          71 :         mode = hapd->iface->current_mode;
     242          71 :         if (mode->mode == HOSTAPD_MODE_IEEE80211A)
     243          36 :                 chan_spacing = 4;
     244             : 
     245          71 :         start = prev = NULL;
     246        1425 :         for (i = 0; i < mode->num_channels; i++) {
     247        1354 :                 struct hostapd_channel_data *chan = &mode->channels[i];
     248        1354 :                 if (chan->flag & HOSTAPD_CHAN_DISABLED)
     249         354 :                         continue;
     250        1929 :                 if (start && prev &&
     251        1828 :                     prev->chan + chan_spacing == chan->chan &&
     252         899 :                     start->max_tx_power == chan->max_tx_power) {
     253         895 :                         prev = chan;
     254         895 :                         continue; /* can use same entry */
     255             :                 }
     256             : 
     257         105 :                 if (start && prev) {
     258          34 :                         pos = hostapd_eid_country_add(pos, end, chan_spacing,
     259             :                                                       start, prev);
     260          34 :                         start = NULL;
     261             :                 }
     262             : 
     263             :                 /* Start new group */
     264         105 :                 start = prev = chan;
     265             :         }
     266             : 
     267          71 :         if (start) {
     268          71 :                 pos = hostapd_eid_country_add(pos, end, chan_spacing,
     269             :                                               start, prev);
     270             :         }
     271             : 
     272          71 :         if ((pos - eid) & 1) {
     273          26 :                 if (end - pos < 1)
     274           0 :                         return eid;
     275          26 :                 *pos++ = 0; /* pad for 16-bit alignment */
     276             :         }
     277             : 
     278          71 :         eid[1] = (pos - eid) - 2;
     279             : 
     280          71 :         return pos;
     281             : }
     282             : 
     283             : 
     284        8552 : static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
     285             : {
     286             :         const u8 *ie;
     287             :         size_t ielen;
     288             : 
     289        8552 :         ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
     290        8552 :         if (ie == NULL || ielen > len)
     291        2662 :                 return eid;
     292             : 
     293        5890 :         os_memcpy(eid, ie, ielen);
     294        5890 :         return eid + ielen;
     295             : }
     296             : 
     297             : 
     298        8552 : static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
     299             : {
     300             :         u8 chan;
     301             : 
     302        8552 :         if (!hapd->cs_freq_params.freq)
     303        8529 :                 return eid;
     304             : 
     305          23 :         if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) ==
     306             :             NUM_HOSTAPD_MODES)
     307           0 :                 return eid;
     308             : 
     309          23 :         *eid++ = WLAN_EID_CHANNEL_SWITCH;
     310          23 :         *eid++ = 3;
     311          23 :         *eid++ = hapd->cs_block_tx;
     312          23 :         *eid++ = chan;
     313          23 :         *eid++ = hapd->cs_count;
     314             : 
     315          23 :         return eid;
     316             : }
     317             : 
     318             : 
     319          23 : static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
     320             : {
     321             :         u8 sec_ch;
     322             : 
     323          23 :         if (!hapd->cs_freq_params.sec_channel_offset)
     324          14 :                 return eid;
     325             : 
     326           9 :         if (hapd->cs_freq_params.sec_channel_offset == -1)
     327           2 :                 sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
     328           7 :         else if (hapd->cs_freq_params.sec_channel_offset == 1)
     329           6 :                 sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
     330             :         else
     331           1 :                 return eid;
     332             : 
     333           8 :         *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
     334           8 :         *eid++ = 1;
     335           8 :         *eid++ = sec_ch;
     336             : 
     337           8 :         return eid;
     338             : }
     339             : 
     340             : 
     341        8552 : static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
     342             :                                   u8 *start, unsigned int *csa_counter_off)
     343             : {
     344        8552 :         u8 *old_pos = pos;
     345             : 
     346        8552 :         if (!csa_counter_off)
     347           0 :                 return pos;
     348             : 
     349        8552 :         *csa_counter_off = 0;
     350        8552 :         pos = hostapd_eid_csa(hapd, pos);
     351             : 
     352        8552 :         if (pos != old_pos) {
     353             :                 /* save an offset to the counter - should be last byte */
     354          23 :                 *csa_counter_off = pos - start - 1;
     355          23 :                 pos = hostapd_eid_secondary_channel(hapd, pos);
     356             :         }
     357             : 
     358        8552 :         return pos;
     359             : }
     360             : 
     361             : 
     362        4052 : static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
     363             :                                    const struct ieee80211_mgmt *req,
     364             :                                    int is_p2p, size_t *resp_len)
     365             : {
     366             :         struct ieee80211_mgmt *resp;
     367             :         u8 *pos, *epos;
     368             :         size_t buflen;
     369             : 
     370             : #define MAX_PROBERESP_LEN 768
     371        4052 :         buflen = MAX_PROBERESP_LEN;
     372             : #ifdef CONFIG_WPS
     373        4052 :         if (hapd->wps_probe_resp_ie)
     374        1739 :                 buflen += wpabuf_len(hapd->wps_probe_resp_ie);
     375             : #endif /* CONFIG_WPS */
     376             : #ifdef CONFIG_P2P
     377         437 :         if (hapd->p2p_probe_resp_ie)
     378         407 :                 buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
     379             : #endif /* CONFIG_P2P */
     380             : #ifdef CONFIG_FST
     381        4052 :         if (hapd->iface->fst_ies)
     382         265 :                 buflen += wpabuf_len(hapd->iface->fst_ies);
     383             : #endif /* CONFIG_FST */
     384        4052 :         if (hapd->conf->vendor_elements)
     385          10 :                 buflen += wpabuf_len(hapd->conf->vendor_elements);
     386        4052 :         if (hapd->conf->vendor_vht) {
     387           2 :                 buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
     388             :                         2 + sizeof(struct ieee80211_vht_operation);
     389             :         }
     390        4052 :         resp = os_zalloc(buflen);
     391        4052 :         if (resp == NULL)
     392           0 :                 return NULL;
     393             : 
     394        4052 :         epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
     395             : 
     396        4052 :         resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     397             :                                            WLAN_FC_STYPE_PROBE_RESP);
     398        4052 :         if (req)
     399        4052 :                 os_memcpy(resp->da, req->sa, ETH_ALEN);
     400        4052 :         os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
     401             : 
     402        4052 :         os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
     403        4052 :         resp->u.probe_resp.beacon_int =
     404        4052 :                 host_to_le16(hapd->iconf->beacon_int);
     405             : 
     406             :         /* hardware or low-level driver will setup seq_ctrl and timestamp */
     407        4052 :         resp->u.probe_resp.capab_info =
     408        4052 :                 host_to_le16(hostapd_own_capab_info(hapd));
     409             : 
     410        4052 :         pos = resp->u.probe_resp.variable;
     411        4052 :         *pos++ = WLAN_EID_SSID;
     412        4052 :         *pos++ = hapd->conf->ssid.ssid_len;
     413        4052 :         os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
     414        4052 :         pos += hapd->conf->ssid.ssid_len;
     415             : 
     416             :         /* Supported rates */
     417        4052 :         pos = hostapd_eid_supp_rates(hapd, pos);
     418             : 
     419             :         /* DS Params */
     420        4052 :         pos = hostapd_eid_ds_params(hapd, pos);
     421             : 
     422        4052 :         pos = hostapd_eid_country(hapd, pos, epos - pos);
     423             : 
     424             :         /* Power Constraint element */
     425        4052 :         pos = hostapd_eid_pwr_constraint(hapd, pos);
     426             : 
     427             :         /* ERP Information element */
     428        4052 :         pos = hostapd_eid_erp_info(hapd, pos);
     429             : 
     430             :         /* Extended supported rates */
     431        4052 :         pos = hostapd_eid_ext_supp_rates(hapd, pos);
     432             : 
     433             :         /* RSN, MDIE, WPA */
     434        4052 :         pos = hostapd_eid_wpa(hapd, pos, epos - pos);
     435             : 
     436        4052 :         pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
     437             : 
     438        4052 :         pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
     439             : 
     440             : #ifdef CONFIG_IEEE80211N
     441        4052 :         pos = hostapd_eid_ht_capabilities(hapd, pos);
     442        4052 :         pos = hostapd_eid_ht_operation(hapd, pos);
     443             : #endif /* CONFIG_IEEE80211N */
     444             : 
     445        4052 :         pos = hostapd_eid_ext_capab(hapd, pos);
     446             : 
     447        4052 :         pos = hostapd_eid_time_adv(hapd, pos);
     448        4052 :         pos = hostapd_eid_time_zone(hapd, pos);
     449             : 
     450        4052 :         pos = hostapd_eid_interworking(hapd, pos);
     451        4052 :         pos = hostapd_eid_adv_proto(hapd, pos);
     452        4052 :         pos = hostapd_eid_roaming_consortium(hapd, pos);
     453             : 
     454        4052 :         pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
     455             :                                     &hapd->cs_c_off_proberesp);
     456             : 
     457             : #ifdef CONFIG_FST
     458        4052 :         if (hapd->iface->fst_ies) {
     459         265 :                 os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
     460             :                           wpabuf_len(hapd->iface->fst_ies));
     461         265 :                 pos += wpabuf_len(hapd->iface->fst_ies);
     462             :         }
     463             : #endif /* CONFIG_FST */
     464             : 
     465             : #ifdef CONFIG_IEEE80211AC
     466        3615 :         if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
     467          18 :                 pos = hostapd_eid_vht_capabilities(hapd, pos);
     468          18 :                 pos = hostapd_eid_vht_operation(hapd, pos);
     469             :         }
     470        3615 :         if (hapd->conf->vendor_vht)
     471           2 :                 pos = hostapd_eid_vendor_vht(hapd, pos);
     472             : #endif /* CONFIG_IEEE80211AC */
     473             : 
     474             :         /* Wi-Fi Alliance WMM */
     475        4052 :         pos = hostapd_eid_wmm(hapd, pos);
     476             : 
     477             : #ifdef CONFIG_WPS
     478        4052 :         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
     479        1739 :                 os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
     480             :                           wpabuf_len(hapd->wps_probe_resp_ie));
     481        1739 :                 pos += wpabuf_len(hapd->wps_probe_resp_ie);
     482             :         }
     483             : #endif /* CONFIG_WPS */
     484             : 
     485             : #ifdef CONFIG_P2P
     486         825 :         if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
     487         388 :             hapd->p2p_probe_resp_ie) {
     488         388 :                 os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
     489             :                           wpabuf_len(hapd->p2p_probe_resp_ie));
     490         388 :                 pos += wpabuf_len(hapd->p2p_probe_resp_ie);
     491             :         }
     492             : #endif /* CONFIG_P2P */
     493             : #ifdef CONFIG_P2P_MANAGER
     494        3615 :         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
     495             :             P2P_MANAGE)
     496           6 :                 pos = hostapd_eid_p2p_manage(hapd, pos);
     497             : #endif /* CONFIG_P2P_MANAGER */
     498             : 
     499             : #ifdef CONFIG_HS20
     500        4052 :         pos = hostapd_eid_hs20_indication(hapd, pos);
     501        4052 :         pos = hostapd_eid_osen(hapd, pos);
     502             : #endif /* CONFIG_HS20 */
     503             : 
     504        4052 :         if (hapd->conf->vendor_elements) {
     505          10 :                 os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
     506             :                           wpabuf_len(hapd->conf->vendor_elements));
     507          10 :                 pos += wpabuf_len(hapd->conf->vendor_elements);
     508             :         }
     509             : 
     510        4052 :         *resp_len = pos - (u8 *) resp;
     511        4052 :         return (u8 *) resp;
     512             : }
     513             : 
     514             : 
     515             : enum ssid_match_result {
     516             :         NO_SSID_MATCH,
     517             :         EXACT_SSID_MATCH,
     518             :         WILDCARD_SSID_MATCH
     519             : };
     520             : 
     521        4194 : static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
     522             :                                          const u8 *ssid, size_t ssid_len,
     523             :                                          const u8 *ssid_list,
     524             :                                          size_t ssid_list_len)
     525             : {
     526             :         const u8 *pos, *end;
     527        4194 :         int wildcard = 0;
     528             : 
     529        4194 :         if (ssid_len == 0)
     530        3588 :                 wildcard = 1;
     531        4698 :         if (ssid_len == hapd->conf->ssid.ssid_len &&
     532         504 :             os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
     533         483 :                 return EXACT_SSID_MATCH;
     534             : 
     535        3711 :         if (ssid_list == NULL)
     536        3711 :                 return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
     537             : 
     538           0 :         pos = ssid_list;
     539           0 :         end = ssid_list + ssid_list_len;
     540           0 :         while (pos + 1 <= end) {
     541           0 :                 if (pos + 2 + pos[1] > end)
     542           0 :                         break;
     543           0 :                 if (pos[1] == 0)
     544           0 :                         wildcard = 1;
     545           0 :                 if (pos[1] == hapd->conf->ssid.ssid_len &&
     546           0 :                     os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
     547           0 :                         return EXACT_SSID_MATCH;
     548           0 :                 pos += 2 + pos[1];
     549             :         }
     550             : 
     551           0 :         return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
     552             : }
     553             : 
     554             : 
     555           6 : void sta_track_expire(struct hostapd_iface *iface, int force)
     556             : {
     557             :         struct os_reltime now;
     558             :         struct hostapd_sta_info *info;
     559             : 
     560           6 :         if (!iface->num_sta_seen)
     561           6 :                 return;
     562             : 
     563           6 :         os_get_reltime(&now);
     564          15 :         while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info,
     565             :                                      list))) {
     566          15 :                 if (!force &&
     567           7 :                     !os_reltime_expired(&now, &info->last_seen,
     568           7 :                                         iface->conf->track_sta_max_age))
     569           5 :                         break;
     570           3 :                 force = 0;
     571             : 
     572          21 :                 wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for "
     573           3 :                            MACSTR, iface->bss[0]->conf->iface,
     574          18 :                            MAC2STR(info->addr));
     575           3 :                 dl_list_del(&info->list);
     576           3 :                 iface->num_sta_seen--;
     577           3 :                 os_free(info);
     578             :         }
     579             : }
     580             : 
     581             : 
     582          39 : static struct hostapd_sta_info * sta_track_get(struct hostapd_iface *iface,
     583             :                                                const u8 *addr)
     584             : {
     585             :         struct hostapd_sta_info *info;
     586             : 
     587          49 :         dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list)
     588          33 :                 if (os_memcmp(addr, info->addr, ETH_ALEN) == 0)
     589          23 :                         return info;
     590             : 
     591          16 :         return NULL;
     592             : }
     593             : 
     594             : 
     595          29 : void sta_track_add(struct hostapd_iface *iface, const u8 *addr)
     596             : {
     597             :         struct hostapd_sta_info *info;
     598             : 
     599          29 :         info = sta_track_get(iface, addr);
     600          29 :         if (info) {
     601             :                 /* Move the most recent entry to the end of the list */
     602          17 :                 dl_list_del(&info->list);
     603          17 :                 dl_list_add_tail(&iface->sta_seen, &info->list);
     604          17 :                 os_get_reltime(&info->last_seen);
     605          46 :                 return;
     606             :         }
     607             : 
     608             :         /* Add a new entry */
     609          12 :         info = os_zalloc(sizeof(*info));
     610          12 :         os_memcpy(info->addr, addr, ETH_ALEN);
     611          12 :         os_get_reltime(&info->last_seen);
     612             : 
     613          12 :         if (iface->num_sta_seen >= iface->conf->track_sta_max_num) {
     614             :                 /* Expire oldest entry to make room for a new one */
     615           1 :                 sta_track_expire(iface, 1);
     616             :         }
     617             : 
     618          84 :         wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for "
     619          84 :                    MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr));
     620          12 :         dl_list_add_tail(&iface->sta_seen, &info->list);
     621          12 :         iface->num_sta_seen++;
     622             : }
     623             : 
     624             : 
     625             : struct hostapd_data *
     626          10 : sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
     627             :                   const char *ifname)
     628             : {
     629          10 :         struct hapd_interfaces *interfaces = iface->interfaces;
     630             :         size_t i, j;
     631             : 
     632          22 :         for (i = 0; i < interfaces->count; i++) {
     633          18 :                 struct hostapd_data *hapd = NULL;
     634             : 
     635          18 :                 iface = interfaces->iface[i];
     636          26 :                 for (j = 0; j < iface->num_bss; j++) {
     637          18 :                         hapd = iface->bss[j];
     638          18 :                         if (os_strcmp(ifname, hapd->conf->iface) == 0)
     639          10 :                                 break;
     640           8 :                         hapd = NULL;
     641             :                 }
     642             : 
     643          18 :                 if (hapd && sta_track_get(iface, addr))
     644           6 :                         return hapd;
     645             :         }
     646             : 
     647           4 :         return NULL;
     648             : }
     649             : 
     650             : 
     651        4220 : void handle_probe_req(struct hostapd_data *hapd,
     652             :                       const struct ieee80211_mgmt *mgmt, size_t len,
     653             :                       int ssi_signal)
     654             : {
     655             :         u8 *resp;
     656             :         struct ieee802_11_elems elems;
     657             :         const u8 *ie;
     658             :         size_t ie_len;
     659             :         size_t i, resp_len;
     660             :         int noack;
     661             :         enum ssid_match_result res;
     662             : 
     663        4220 :         ie = mgmt->u.probe_req.variable;
     664        4220 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
     665         168 :                 return;
     666        4220 :         if (hapd->iconf->track_sta_max_num)
     667          18 :                 sta_track_add(hapd->iface, mgmt->sa);
     668        4220 :         ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
     669             : 
     670        6418 :         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
     671        4402 :                 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
     672        2201 :                                             mgmt->sa, mgmt->da, mgmt->bssid,
     673             :                                             ie, ie_len, ssi_signal) > 0)
     674           3 :                         return;
     675             : 
     676        4217 :         if (!hapd->iconf->send_probe_response)
     677           0 :                 return;
     678             : 
     679        4217 :         if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
     680           0 :                 wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
     681           0 :                            MAC2STR(mgmt->sa));
     682           0 :                 return;
     683             :         }
     684             : 
     685        4217 :         if ((!elems.ssid || !elems.supp_rates)) {
     686           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
     687             :                            "without SSID or supported rates element",
     688           0 :                            MAC2STR(mgmt->sa));
     689           0 :                 return;
     690             :         }
     691             : 
     692             :         /*
     693             :          * No need to reply if the Probe Request frame was sent on an adjacent
     694             :          * channel. IEEE Std 802.11-2012 describes this as a requirement for an
     695             :          * AP with dot11RadioMeasurementActivated set to true, but strictly
     696             :          * speaking does not allow such ignoring of Probe Request frames if
     697             :          * dot11RadioMeasurementActivated is false. Anyway, this can help reduce
     698             :          * number of unnecessary Probe Response frames for cases where the STA
     699             :          * is less likely to see them (Probe Request frame sent on a
     700             :          * neighboring, but partially overlapping, channel).
     701             :          */
     702        7992 :         if (elems.ds_params &&
     703        7550 :             hapd->iface->current_mode &&
     704        3778 :             (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G ||
     705        3778 :              hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) &&
     706        3775 :             hapd->iconf->channel != elems.ds_params[0]) {
     707           2 :                 wpa_printf(MSG_DEBUG,
     708             :                            "Ignore Probe Request due to DS Params mismatch: chan=%u != ds.chan=%u",
     709           2 :                            hapd->iconf->channel, elems.ds_params[0]);
     710           1 :                 return;
     711             :         }
     712             : 
     713             : #ifdef CONFIG_P2P
     714         444 :         if (hapd->p2p && elems.wps_ie) {
     715             :                 struct wpabuf *wps;
     716         425 :                 wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
     717         425 :                 if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
     718           3 :                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
     719             :                                    "due to mismatch with Requested Device "
     720             :                                    "Type");
     721           3 :                         wpabuf_free(wps);
     722           3 :                         return;
     723             :                 }
     724         422 :                 wpabuf_free(wps);
     725             :         }
     726             : 
     727         441 :         if (hapd->p2p && elems.p2p) {
     728             :                 struct wpabuf *p2p;
     729         420 :                 p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
     730         420 :                 if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
     731           3 :                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
     732             :                                    "due to mismatch with Device ID");
     733           3 :                         wpabuf_free(p2p);
     734           3 :                         return;
     735             :                 }
     736         417 :                 wpabuf_free(p2p);
     737             :         }
     738             : #endif /* CONFIG_P2P */
     739             : 
     740        4226 :         if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
     741          16 :             elems.ssid_list_len == 0) {
     742          96 :                 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
     743          96 :                            "broadcast SSID ignored", MAC2STR(mgmt->sa));
     744          16 :                 return;
     745             :         }
     746             : 
     747             : #ifdef CONFIG_P2P
     748         846 :         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
     749         547 :             elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
     750         139 :             os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
     751             :                       P2P_WILDCARD_SSID_LEN) == 0) {
     752             :                 /* Process P2P Wildcard SSID like Wildcard SSID */
     753         139 :                 elems.ssid_len = 0;
     754             :         }
     755             : #endif /* CONFIG_P2P */
     756             : 
     757        4194 :         res = ssid_match(hapd, elems.ssid, elems.ssid_len,
     758        4194 :                          elems.ssid_list, elems.ssid_list_len);
     759        4194 :         if (res == NO_SSID_MATCH) {
     760         123 :                 if (!(mgmt->da[0] & 0x01)) {
     761           0 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     762             :                                    " for foreign SSID '%s' (DA " MACSTR ")%s",
     763           0 :                                    MAC2STR(mgmt->sa),
     764           0 :                                    wpa_ssid_txt(elems.ssid, elems.ssid_len),
     765           0 :                                    MAC2STR(mgmt->da),
     766           0 :                                    elems.ssid_list ? " (SSID list)" : "");
     767             :                 }
     768         123 :                 return;
     769             :         }
     770             : 
     771             : #ifdef CONFIG_INTERWORKING
     772        4391 :         if (hapd->conf->interworking &&
     773         600 :             elems.interworking && elems.interworking_len >= 1) {
     774         280 :                 u8 ant = elems.interworking[0] & 0x0f;
     775         290 :                 if (ant != INTERWORKING_ANT_WILDCARD &&
     776          10 :                     ant != hapd->conf->access_network_type) {
     777          35 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     778             :                                    " for mismatching ANT %u ignored",
     779          30 :                                    MAC2STR(mgmt->sa), ant);
     780           5 :                         return;
     781             :                 }
     782             :         }
     783             : 
     784        4341 :         if (hapd->conf->interworking && elems.interworking &&
     785         545 :             (elems.interworking_len == 7 || elems.interworking_len == 9)) {
     786             :                 const u8 *hessid;
     787           5 :                 if (elems.interworking_len == 7)
     788           5 :                         hessid = elems.interworking + 1;
     789             :                 else
     790           0 :                         hessid = elems.interworking + 1 + 2;
     791          10 :                 if (!is_broadcast_ether_addr(hessid) &&
     792           5 :                     os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
     793          36 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     794             :                                    " for mismatching HESSID " MACSTR
     795             :                                    " ignored",
     796          36 :                                    MAC2STR(mgmt->sa), MAC2STR(hessid));
     797           3 :                         return;
     798             :                 }
     799             :         }
     800             : #endif /* CONFIG_INTERWORKING */
     801             : 
     802             : #ifdef CONFIG_P2P
     803         844 :         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
     804         407 :             supp_rates_11b_only(&elems)) {
     805             :                 /* Indicates support for 11b rates only */
     806           0 :                 wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
     807             :                            MACSTR " with only 802.11b rates",
     808           0 :                            MAC2STR(mgmt->sa));
     809           0 :                 return;
     810             :         }
     811             : #endif /* CONFIG_P2P */
     812             : 
     813             :         /* TODO: verify that supp_rates contains at least one matching rate
     814             :          * with AP configuration */
     815             : 
     816        4069 :         if (hapd->conf->no_probe_resp_if_seen_on &&
     817          12 :             is_multicast_ether_addr(mgmt->da) &&
     818          12 :             is_multicast_ether_addr(mgmt->bssid) &&
     819           6 :             sta_track_seen_on(hapd->iface, mgmt->sa,
     820           6 :                               hapd->conf->no_probe_resp_if_seen_on)) {
     821          24 :                 wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
     822             :                            " since STA has been seen on %s",
     823          21 :                            hapd->conf->iface, MAC2STR(mgmt->sa),
     824           3 :                            hapd->conf->no_probe_resp_if_seen_on);
     825           3 :                 return;
     826             :         }
     827             : 
     828             : #ifdef CONFIG_TESTING_OPTIONS
     829        4071 :         if (hapd->iconf->ignore_probe_probability > 0.0 &&
     830          11 :             drand48() < hapd->iconf->ignore_probe_probability) {
     831          48 :                 wpa_printf(MSG_INFO,
     832             :                            "TESTING: ignoring probe request from " MACSTR,
     833          48 :                            MAC2STR(mgmt->sa));
     834           8 :                 return;
     835             :         }
     836             : #endif /* CONFIG_TESTING_OPTIONS */
     837             : 
     838        4052 :         resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
     839             :                                       &resp_len);
     840        4052 :         if (resp == NULL)
     841           0 :                 return;
     842             : 
     843             :         /*
     844             :          * If this is a broadcast probe request, apply no ack policy to avoid
     845             :          * excessive retries.
     846             :          */
     847        7621 :         noack = !!(res == WILDCARD_SSID_MATCH &&
     848        3569 :                    is_broadcast_ether_addr(mgmt->da));
     849             : 
     850        4052 :         if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
     851           4 :                 wpa_printf(MSG_INFO, "handle_probe_req: send failed");
     852             : 
     853        4052 :         os_free(resp);
     854             : 
     855       28364 :         wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
     856       24312 :                    "SSID", MAC2STR(mgmt->sa),
     857        4052 :                    elems.ssid_len == 0 ? "broadcast" : "our");
     858             : }
     859             : 
     860             : 
     861        4500 : static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
     862             :                                         size_t *resp_len)
     863             : {
     864             :         /* check probe response offloading caps and print warnings */
     865        4500 :         if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
     866        4500 :                 return NULL;
     867             : 
     868             : #ifdef CONFIG_WPS
     869           0 :         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
     870           0 :             (!(hapd->iface->probe_resp_offloads &
     871             :                (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
     872             :                 WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
     873           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
     874             :                            "Probe Response while not supporting this");
     875             : #endif /* CONFIG_WPS */
     876             : 
     877             : #ifdef CONFIG_P2P
     878           0 :         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
     879           0 :             !(hapd->iface->probe_resp_offloads &
     880             :               WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
     881           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
     882             :                            "Probe Response while not supporting this");
     883             : #endif  /* CONFIG_P2P */
     884             : 
     885           0 :         if (hapd->conf->interworking &&
     886           0 :             !(hapd->iface->probe_resp_offloads &
     887             :               WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
     888           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload "
     889             :                            "Interworking Probe Response while not supporting "
     890             :                            "this");
     891             : 
     892             :         /* Generate a Probe Response template for the non-P2P case */
     893           0 :         return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len);
     894             : }
     895             : 
     896             : #endif /* NEED_AP_MLME */
     897             : 
     898             : 
     899        4502 : int ieee802_11_build_ap_params(struct hostapd_data *hapd,
     900             :                                struct wpa_driver_ap_params *params)
     901             : {
     902        4502 :         struct ieee80211_mgmt *head = NULL;
     903        4502 :         u8 *tail = NULL;
     904        4502 :         size_t head_len = 0, tail_len = 0;
     905        4502 :         u8 *resp = NULL;
     906        4502 :         size_t resp_len = 0;
     907             : #ifdef NEED_AP_MLME
     908             :         u16 capab_info;
     909             :         u8 *pos, *tailpos;
     910             : 
     911             : #define BEACON_HEAD_BUF_SIZE 256
     912             : #define BEACON_TAIL_BUF_SIZE 512
     913        4502 :         head = os_zalloc(BEACON_HEAD_BUF_SIZE);
     914        4502 :         tail_len = BEACON_TAIL_BUF_SIZE;
     915             : #ifdef CONFIG_WPS
     916        4502 :         if (hapd->conf->wps_state && hapd->wps_beacon_ie)
     917        2327 :                 tail_len += wpabuf_len(hapd->wps_beacon_ie);
     918             : #endif /* CONFIG_WPS */
     919             : #ifdef CONFIG_P2P
     920        1696 :         if (hapd->p2p_beacon_ie)
     921        1603 :                 tail_len += wpabuf_len(hapd->p2p_beacon_ie);
     922             : #endif /* CONFIG_P2P */
     923             : #ifdef CONFIG_FST
     924        4502 :         if (hapd->iface->fst_ies)
     925         266 :                 tail_len += wpabuf_len(hapd->iface->fst_ies);
     926             : #endif /* CONFIG_FST */
     927        4502 :         if (hapd->conf->vendor_elements)
     928           7 :                 tail_len += wpabuf_len(hapd->conf->vendor_elements);
     929             : 
     930             : #ifdef CONFIG_IEEE80211AC
     931        2806 :         if (hapd->conf->vendor_vht) {
     932           1 :                 tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
     933             :                         2 + sizeof(struct ieee80211_vht_operation);
     934             :         }
     935             : #endif /* CONFIG_IEEE80211AC */
     936             : 
     937        4502 :         tailpos = tail = os_malloc(tail_len);
     938        4502 :         if (head == NULL || tail == NULL) {
     939           2 :                 wpa_printf(MSG_ERROR, "Failed to set beacon data");
     940           2 :                 os_free(head);
     941           2 :                 os_free(tail);
     942           2 :                 return -1;
     943             :         }
     944             : 
     945        4500 :         head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     946             :                                            WLAN_FC_STYPE_BEACON);
     947        4500 :         head->duration = host_to_le16(0);
     948        4500 :         os_memset(head->da, 0xff, ETH_ALEN);
     949             : 
     950        4500 :         os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
     951        4500 :         os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
     952        4500 :         head->u.beacon.beacon_int =
     953        4500 :                 host_to_le16(hapd->iconf->beacon_int);
     954             : 
     955             :         /* hardware or low-level driver will setup seq_ctrl and timestamp */
     956        4500 :         capab_info = hostapd_own_capab_info(hapd);
     957        4500 :         head->u.beacon.capab_info = host_to_le16(capab_info);
     958        4500 :         pos = &head->u.beacon.variable[0];
     959             : 
     960             :         /* SSID */
     961        4500 :         *pos++ = WLAN_EID_SSID;
     962        4500 :         if (hapd->conf->ignore_broadcast_ssid == 2) {
     963             :                 /* clear the data, but keep the correct length of the SSID */
     964           1 :                 *pos++ = hapd->conf->ssid.ssid_len;
     965           1 :                 os_memset(pos, 0, hapd->conf->ssid.ssid_len);
     966           1 :                 pos += hapd->conf->ssid.ssid_len;
     967        4499 :         } else if (hapd->conf->ignore_broadcast_ssid) {
     968           9 :                 *pos++ = 0; /* empty SSID */
     969             :         } else {
     970        4490 :                 *pos++ = hapd->conf->ssid.ssid_len;
     971        4490 :                 os_memcpy(pos, hapd->conf->ssid.ssid,
     972             :                           hapd->conf->ssid.ssid_len);
     973        4490 :                 pos += hapd->conf->ssid.ssid_len;
     974             :         }
     975             : 
     976             :         /* Supported rates */
     977        4500 :         pos = hostapd_eid_supp_rates(hapd, pos);
     978             : 
     979             :         /* DS Params */
     980        4500 :         pos = hostapd_eid_ds_params(hapd, pos);
     981             : 
     982        4500 :         head_len = pos - (u8 *) head;
     983             : 
     984        4500 :         tailpos = hostapd_eid_country(hapd, tailpos,
     985        4500 :                                       tail + BEACON_TAIL_BUF_SIZE - tailpos);
     986             : 
     987             :         /* Power Constraint element */
     988        4500 :         tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
     989             : 
     990             :         /* ERP Information element */
     991        4500 :         tailpos = hostapd_eid_erp_info(hapd, tailpos);
     992             : 
     993             :         /* Extended supported rates */
     994        4500 :         tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
     995             : 
     996             :         /* RSN, MDIE, WPA */
     997        4500 :         tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
     998             :                                   tailpos);
     999             : 
    1000        4500 :         tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
    1001        4500 :                                                tail + BEACON_TAIL_BUF_SIZE -
    1002             :                                                tailpos);
    1003             : 
    1004        4500 :         tailpos = hostapd_eid_bss_load(hapd, tailpos,
    1005        4500 :                                        tail + BEACON_TAIL_BUF_SIZE - tailpos);
    1006             : 
    1007             : #ifdef CONFIG_IEEE80211N
    1008        4500 :         tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
    1009        4500 :         tailpos = hostapd_eid_ht_operation(hapd, tailpos);
    1010             : #endif /* CONFIG_IEEE80211N */
    1011             : 
    1012        4500 :         tailpos = hostapd_eid_ext_capab(hapd, tailpos);
    1013             : 
    1014             :         /*
    1015             :          * TODO: Time Advertisement element should only be included in some
    1016             :          * DTIM Beacon frames.
    1017             :          */
    1018        4500 :         tailpos = hostapd_eid_time_adv(hapd, tailpos);
    1019             : 
    1020        4500 :         tailpos = hostapd_eid_interworking(hapd, tailpos);
    1021        4500 :         tailpos = hostapd_eid_adv_proto(hapd, tailpos);
    1022        4500 :         tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
    1023        4500 :         tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
    1024             :                                         &hapd->cs_c_off_beacon);
    1025             : 
    1026             : #ifdef CONFIG_FST
    1027        4500 :         if (hapd->iface->fst_ies) {
    1028         266 :                 os_memcpy(tailpos, wpabuf_head(hapd->iface->fst_ies),
    1029             :                           wpabuf_len(hapd->iface->fst_ies));
    1030         266 :                 tailpos += wpabuf_len(hapd->iface->fst_ies);
    1031             :         }
    1032             : #endif /* CONFIG_FST */
    1033             : 
    1034             : #ifdef CONFIG_IEEE80211AC
    1035        2804 :         if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
    1036          21 :                 tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
    1037          21 :                 tailpos = hostapd_eid_vht_operation(hapd, tailpos);
    1038             :         }
    1039        2804 :         if (hapd->conf->vendor_vht)
    1040           1 :                 tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
    1041             : #endif /* CONFIG_IEEE80211AC */
    1042             : 
    1043             :         /* Wi-Fi Alliance WMM */
    1044        4500 :         tailpos = hostapd_eid_wmm(hapd, tailpos);
    1045             : 
    1046             : #ifdef CONFIG_WPS
    1047        4500 :         if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
    1048        2327 :                 os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
    1049             :                           wpabuf_len(hapd->wps_beacon_ie));
    1050        2327 :                 tailpos += wpabuf_len(hapd->wps_beacon_ie);
    1051             :         }
    1052             : #endif /* CONFIG_WPS */
    1053             : 
    1054             : #ifdef CONFIG_P2P
    1055        1696 :         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
    1056        1603 :                 os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
    1057             :                           wpabuf_len(hapd->p2p_beacon_ie));
    1058        1603 :                 tailpos += wpabuf_len(hapd->p2p_beacon_ie);
    1059             :         }
    1060             : #endif /* CONFIG_P2P */
    1061             : #ifdef CONFIG_P2P_MANAGER
    1062        2804 :         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
    1063             :             P2P_MANAGE)
    1064           5 :                 tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
    1065             : #endif /* CONFIG_P2P_MANAGER */
    1066             : 
    1067             : #ifdef CONFIG_HS20
    1068        4500 :         tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
    1069        4500 :         tailpos = hostapd_eid_osen(hapd, tailpos);
    1070             : #endif /* CONFIG_HS20 */
    1071             : 
    1072        4500 :         if (hapd->conf->vendor_elements) {
    1073           7 :                 os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
    1074             :                           wpabuf_len(hapd->conf->vendor_elements));
    1075           7 :                 tailpos += wpabuf_len(hapd->conf->vendor_elements);
    1076             :         }
    1077             : 
    1078        4500 :         tail_len = tailpos > tail ? tailpos - tail : 0;
    1079             : 
    1080        4500 :         resp = hostapd_probe_resp_offloads(hapd, &resp_len);
    1081             : #endif /* NEED_AP_MLME */
    1082             : 
    1083        4500 :         os_memset(params, 0, sizeof(*params));
    1084        4500 :         params->head = (u8 *) head;
    1085        4500 :         params->head_len = head_len;
    1086        4500 :         params->tail = tail;
    1087        4500 :         params->tail_len = tail_len;
    1088        4500 :         params->proberesp = resp;
    1089        4500 :         params->proberesp_len = resp_len;
    1090        4500 :         params->dtim_period = hapd->conf->dtim_period;
    1091        4500 :         params->beacon_int = hapd->iconf->beacon_int;
    1092        4500 :         params->basic_rates = hapd->iface->basic_rates;
    1093        4500 :         params->ssid = hapd->conf->ssid.ssid;
    1094        4500 :         params->ssid_len = hapd->conf->ssid.ssid_len;
    1095        4500 :         if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
    1096             :             (WPA_PROTO_WPA | WPA_PROTO_RSN))
    1097         188 :                 params->pairwise_ciphers = hapd->conf->wpa_pairwise |
    1098          94 :                         hapd->conf->rsn_pairwise;
    1099        4406 :         else if (hapd->conf->wpa & WPA_PROTO_RSN)
    1100        2891 :                 params->pairwise_ciphers = hapd->conf->rsn_pairwise;
    1101        1515 :         else if (hapd->conf->wpa & WPA_PROTO_WPA)
    1102          44 :                 params->pairwise_ciphers = hapd->conf->wpa_pairwise;
    1103        4500 :         params->group_cipher = hapd->conf->wpa_group;
    1104        4500 :         params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
    1105        4500 :         params->auth_algs = hapd->conf->auth_algs;
    1106        4500 :         params->wpa_version = hapd->conf->wpa;
    1107        9003 :         params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
    1108        1441 :                 (hapd->conf->ieee802_1x &&
    1109          19 :                  (hapd->conf->default_wep_key_len ||
    1110           8 :                   hapd->conf->individual_wep_key_len));
    1111        4500 :         switch (hapd->conf->ignore_broadcast_ssid) {
    1112             :         case 0:
    1113        4490 :                 params->hide_ssid = NO_SSID_HIDING;
    1114        4490 :                 break;
    1115             :         case 1:
    1116           9 :                 params->hide_ssid = HIDDEN_SSID_ZERO_LEN;
    1117           9 :                 break;
    1118             :         case 2:
    1119           1 :                 params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
    1120           1 :                 break;
    1121             :         }
    1122        4500 :         params->isolate = hapd->conf->isolate;
    1123        4500 :         params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
    1124             : #ifdef NEED_AP_MLME
    1125        4500 :         params->cts_protect = !!(ieee802_11_erp_info(hapd) &
    1126             :                                 ERP_INFO_USE_PROTECTION);
    1127        8955 :         params->preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
    1128        4455 :                 hapd->iconf->preamble == SHORT_PREAMBLE;
    1129        8988 :         if (hapd->iface->current_mode &&
    1130        4488 :             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
    1131        3923 :                 params->short_slot_time =
    1132        3923 :                         hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
    1133             :         else
    1134         577 :                 params->short_slot_time = -1;
    1135        4500 :         if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
    1136         149 :                 params->ht_opmode = -1;
    1137             :         else
    1138        4351 :                 params->ht_opmode = hapd->iface->ht_op_mode;
    1139             : #endif /* NEED_AP_MLME */
    1140        4500 :         params->interworking = hapd->conf->interworking;
    1141        4626 :         if (hapd->conf->interworking &&
    1142         126 :             !is_zero_ether_addr(hapd->conf->hessid))
    1143          58 :                 params->hessid = hapd->conf->hessid;
    1144        4500 :         params->access_network_type = hapd->conf->access_network_type;
    1145        4500 :         params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
    1146             : #ifdef CONFIG_P2P
    1147        1696 :         params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow;
    1148             : #endif /* CONFIG_P2P */
    1149             : #ifdef CONFIG_HS20
    1150        4500 :         params->disable_dgaf = hapd->conf->disable_dgaf;
    1151        4500 :         if (hapd->conf->osen) {
    1152           1 :                 params->privacy = 1;
    1153           1 :                 params->osen = 1;
    1154             :         }
    1155             : #endif /* CONFIG_HS20 */
    1156        4500 :         return 0;
    1157             : }
    1158             : 
    1159             : 
    1160        4500 : void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
    1161             : {
    1162        4500 :         os_free(params->tail);
    1163        4500 :         params->tail = NULL;
    1164        4500 :         os_free(params->head);
    1165        4500 :         params->head = NULL;
    1166        4500 :         os_free(params->proberesp);
    1167        4500 :         params->proberesp = NULL;
    1168        4500 : }
    1169             : 
    1170             : 
    1171        4456 : int ieee802_11_set_beacon(struct hostapd_data *hapd)
    1172             : {
    1173             :         struct wpa_driver_ap_params params;
    1174             :         struct hostapd_freq_params freq;
    1175        4456 :         struct hostapd_iface *iface = hapd->iface;
    1176        4456 :         struct hostapd_config *iconf = iface->conf;
    1177             :         struct wpabuf *beacon, *proberesp, *assocresp;
    1178        4456 :         int res, ret = -1;
    1179             : 
    1180        4456 :         if (hapd->csa_in_progress) {
    1181           0 :                 wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
    1182           0 :                 return -1;
    1183             :         }
    1184             : 
    1185        4456 :         hapd->beacon_set_done = 1;
    1186             : 
    1187        4456 :         if (ieee802_11_build_ap_params(hapd, &params) < 0)
    1188           2 :                 return -1;
    1189             : 
    1190        4454 :         if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
    1191             :             0)
    1192           0 :                 goto fail;
    1193             : 
    1194        4454 :         params.beacon_ies = beacon;
    1195        4454 :         params.proberesp_ies = proberesp;
    1196        4454 :         params.assocresp_ies = assocresp;
    1197        4454 :         params.reenable = hapd->reenable_beacon;
    1198        4454 :         hapd->reenable_beacon = 0;
    1199             : 
    1200        8896 :         if (iface->current_mode &&
    1201       22210 :             hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
    1202        4442 :                                     iconf->channel, iconf->ieee80211n,
    1203             :                                     iconf->ieee80211ac,
    1204             :                                     iconf->secondary_channel,
    1205        4442 :                                     iconf->vht_oper_chwidth,
    1206        4442 :                                     iconf->vht_oper_centr_freq_seg0_idx,
    1207        4442 :                                     iconf->vht_oper_centr_freq_seg1_idx,
    1208        4442 :                                     iface->current_mode->vht_capab) == 0)
    1209        4442 :                 params.freq = &freq;
    1210             : 
    1211        4454 :         res = hostapd_drv_set_ap(hapd, &params);
    1212        4454 :         hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
    1213        4454 :         if (res)
    1214          63 :                 wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
    1215             :         else
    1216        4391 :                 ret = 0;
    1217             : fail:
    1218        4454 :         ieee802_11_free_ap_params(&params);
    1219        4454 :         return ret;
    1220             : }
    1221             : 
    1222             : 
    1223         901 : int ieee802_11_set_beacons(struct hostapd_iface *iface)
    1224             : {
    1225             :         size_t i;
    1226         901 :         int ret = 0;
    1227             : 
    1228        1806 :         for (i = 0; i < iface->num_bss; i++) {
    1229        1810 :                 if (iface->bss[i]->started &&
    1230         905 :                     ieee802_11_set_beacon(iface->bss[i]) < 0)
    1231          62 :                         ret = -1;
    1232             :         }
    1233             : 
    1234         901 :         return ret;
    1235             : }
    1236             : 
    1237             : 
    1238             : /* only update beacons if started */
    1239           7 : int ieee802_11_update_beacons(struct hostapd_iface *iface)
    1240             : {
    1241             :         size_t i;
    1242           7 :         int ret = 0;
    1243             : 
    1244          14 :         for (i = 0; i < iface->num_bss; i++) {
    1245          14 :                 if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
    1246           7 :                     ieee802_11_set_beacon(iface->bss[i]) < 0)
    1247           0 :                         ret = -1;
    1248             :         }
    1249             : 
    1250           7 :         return ret;
    1251             : }
    1252             : 
    1253             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10