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 1422976643 Lines: 493 548 90.0 %
Date: 2015-02-03 Functions: 21 21 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 "wps/wps_defs.h"
      19             : #include "p2p/p2p.h"
      20             : #include "hostapd.h"
      21             : #include "ieee802_11.h"
      22             : #include "wpa_auth.h"
      23             : #include "wmm.h"
      24             : #include "ap_config.h"
      25             : #include "sta_info.h"
      26             : #include "p2p_hostapd.h"
      27             : #include "ap_drv_ops.h"
      28             : #include "beacon.h"
      29             : #include "hs20.h"
      30             : #include "dfs.h"
      31             : 
      32             : 
      33             : #ifdef NEED_AP_MLME
      34             : 
      35        5053 : static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
      36             :                                          size_t len)
      37             : {
      38        5053 :         if (!hapd->conf->radio_measurements || len < 2 + 4)
      39        5051 :                 return eid;
      40             : 
      41           2 :         *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
      42           2 :         *eid++ = 5;
      43           2 :         *eid++ = (hapd->conf->radio_measurements & BIT(0)) ?
      44             :                 WLAN_RRM_CAPS_NEIGHBOR_REPORT : 0x00;
      45           2 :         *eid++ = 0x00;
      46           2 :         *eid++ = 0x00;
      47           2 :         *eid++ = 0x00;
      48           2 :         *eid++ = 0x00;
      49           2 :         return eid;
      50             : }
      51             : 
      52             : 
      53        5053 : static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
      54             : {
      55        5053 :         if (len < 2 + 5)
      56           0 :                 return eid;
      57             : 
      58             : #ifdef CONFIG_TESTING_OPTIONS
      59        5053 :         if (hapd->conf->bss_load_test_set) {
      60          11 :                 *eid++ = WLAN_EID_BSS_LOAD;
      61          11 :                 *eid++ = 5;
      62          11 :                 os_memcpy(eid, hapd->conf->bss_load_test, 5);
      63          11 :                 eid += 5;
      64          11 :                 return eid;
      65             :         }
      66             : #endif /* CONFIG_TESTING_OPTIONS */
      67        5042 :         if (hapd->conf->bss_load_update_period) {
      68           7 :                 *eid++ = WLAN_EID_BSS_LOAD;
      69           7 :                 *eid++ = 5;
      70           7 :                 WPA_PUT_LE16(eid, hapd->num_sta);
      71           7 :                 eid += 2;
      72           7 :                 *eid++ = hapd->iface->channel_utilization;
      73           7 :                 WPA_PUT_LE16(eid, 0); /* no available admission capabity */
      74           7 :                 eid += 2;
      75             :         }
      76        5042 :         return eid;
      77             : }
      78             : 
      79             : 
      80        7623 : static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
      81             : {
      82        7623 :         u8 erp = 0;
      83             : 
      84       15236 :         if (hapd->iface->current_mode == NULL ||
      85        7613 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
      86         126 :                 return 0;
      87             : 
      88        7497 :         if (hapd->iface->olbc)
      89           2 :                 erp |= ERP_INFO_USE_PROTECTION;
      90        7497 :         if (hapd->iface->num_sta_non_erp > 0) {
      91           0 :                 erp |= ERP_INFO_NON_ERP_PRESENT |
      92             :                         ERP_INFO_USE_PROTECTION;
      93             :         }
      94       14994 :         if (hapd->iface->num_sta_no_short_preamble > 0 ||
      95        7497 :             hapd->iconf->preamble == LONG_PREAMBLE)
      96        7494 :                 erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
      97             : 
      98        7497 :         return erp;
      99             : }
     100             : 
     101             : 
     102        5053 : static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
     103             : {
     104        5053 :         *eid++ = WLAN_EID_DS_PARAMS;
     105        5053 :         *eid++ = 1;
     106        5053 :         *eid++ = hapd->iconf->channel;
     107        5053 :         return eid;
     108             : }
     109             : 
     110             : 
     111        5053 : static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
     112             : {
     113       10096 :         if (hapd->iface->current_mode == NULL ||
     114        5043 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
     115         172 :                 return eid;
     116             : 
     117             :         /* Set NonERP_present and use_protection bits if there
     118             :          * are any associated NonERP stations. */
     119             :         /* TODO: use_protection bit can be set to zero even if
     120             :          * there are NonERP stations present. This optimization
     121             :          * might be useful if NonERP stations are "quiet".
     122             :          * See 802.11g/D6 E-1 for recommended practice.
     123             :          * In addition, Non ERP present might be set, if AP detects Non ERP
     124             :          * operation on other APs. */
     125             : 
     126             :         /* Add ERP Information element */
     127        4881 :         *eid++ = WLAN_EID_ERP_INFO;
     128        4881 :         *eid++ = 1;
     129        4881 :         *eid++ = ieee802_11_erp_info(hapd);
     130             : 
     131        4881 :         return eid;
     132             : }
     133             : 
     134             : 
     135        5053 : static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid)
     136             : {
     137        5053 :         u8 *pos = eid;
     138        5053 :         u8 local_pwr_constraint = 0;
     139             :         int dfs;
     140             : 
     141       10096 :         if (hapd->iface->current_mode == NULL ||
     142        5043 :             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
     143        4901 :                 return eid;
     144             : 
     145             :         /* Let host drivers add this IE if DFS support is offloaded */
     146         152 :         if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
     147           0 :                 return eid;
     148             : 
     149             :         /*
     150             :          * There is no DFS support and power constraint was not directly
     151             :          * requested by config option.
     152             :          */
     153         278 :         if (!hapd->iconf->ieee80211h &&
     154         126 :             hapd->iconf->local_pwr_constraint == -1)
     155         124 :                 return eid;
     156             : 
     157             :         /* Check if DFS is required by regulatory. */
     158          28 :         dfs = hostapd_is_dfs_required(hapd->iface);
     159          28 :         if (dfs < 0) {
     160           0 :                 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
     161             :                            dfs);
     162           0 :                 dfs = 0;
     163             :         }
     164             : 
     165          28 :         if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1)
     166          14 :                 return eid;
     167             : 
     168             :         /*
     169             :          * ieee80211h (DFS) is enabled so Power Constraint element shall
     170             :          * be added when running on DFS channel whenever local_pwr_constraint
     171             :          * is configured or not. In order to meet regulations when TPC is not
     172             :          * implemented using a transmit power that is below the legal maximum
     173             :          * (including any mitigation factor) should help. In this case,
     174             :          * indicate 3 dB below maximum allowed transmit power.
     175             :          */
     176          14 :         if (hapd->iconf->local_pwr_constraint == -1)
     177          12 :                 local_pwr_constraint = 3;
     178             : 
     179             :         /*
     180             :          * A STA that is not an AP shall use a transmit power less than or
     181             :          * equal to the local maximum transmit power level for the channel.
     182             :          * The local maximum transmit power can be calculated from the formula:
     183             :          * local max TX pwr = max TX pwr - local pwr constraint
     184             :          * Where max TX pwr is maximum transmit power level specified for
     185             :          * channel in Country element and local pwr constraint is specified
     186             :          * for channel in this Power Constraint element.
     187             :          */
     188             : 
     189             :         /* Element ID */
     190          14 :         *pos++ = WLAN_EID_PWR_CONSTRAINT;
     191             :         /* Length */
     192          14 :         *pos++ = 1;
     193             :         /* Local Power Constraint */
     194          14 :         if (local_pwr_constraint)
     195          12 :                 *pos++ = local_pwr_constraint;
     196             :         else
     197           2 :                 *pos++ = hapd->iconf->local_pwr_constraint;
     198             : 
     199          14 :         return pos;
     200             : }
     201             : 
     202             : 
     203          61 : static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
     204             :                                     struct hostapd_channel_data *start,
     205             :                                     struct hostapd_channel_data *prev)
     206             : {
     207          61 :         if (end - pos < 3)
     208           0 :                 return pos;
     209             : 
     210             :         /* first channel number */
     211          61 :         *pos++ = start->chan;
     212             :         /* number of channels */
     213          61 :         *pos++ = (prev->chan - start->chan) / chan_spacing + 1;
     214             :         /* maximum transmit power level */
     215          61 :         *pos++ = start->max_tx_power;
     216             : 
     217          61 :         return pos;
     218             : }
     219             : 
     220             : 
     221        5053 : static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
     222             :                                 int max_len)
     223             : {
     224        5053 :         u8 *pos = eid;
     225        5053 :         u8 *end = eid + max_len;
     226             :         int i;
     227             :         struct hostapd_hw_modes *mode;
     228             :         struct hostapd_channel_data *start, *prev;
     229        5053 :         int chan_spacing = 1;
     230             : 
     231        5088 :         if (!hapd->iconf->ieee80211d || max_len < 6 ||
     232          35 :             hapd->iface->current_mode == NULL)
     233        5018 :                 return eid;
     234             : 
     235          35 :         *pos++ = WLAN_EID_COUNTRY;
     236          35 :         pos++; /* length will be set later */
     237          35 :         os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
     238          35 :         pos += 3;
     239             : 
     240          35 :         mode = hapd->iface->current_mode;
     241          35 :         if (mode->mode == HOSTAPD_MODE_IEEE80211A)
     242          32 :                 chan_spacing = 4;
     243             : 
     244          35 :         start = prev = NULL;
     245         845 :         for (i = 0; i < mode->num_channels; i++) {
     246         810 :                 struct hostapd_channel_data *chan = &mode->channels[i];
     247         810 :                 if (chan->flag & HOSTAPD_CHAN_DISABLED)
     248         253 :                         continue;
     249        1079 :                 if (start && prev &&
     250        1018 :                     prev->chan + chan_spacing == chan->chan &&
     251         496 :                     start->max_tx_power == chan->max_tx_power) {
     252         496 :                         prev = chan;
     253         496 :                         continue; /* can use same entry */
     254             :                 }
     255             : 
     256          61 :                 if (start && prev) {
     257          26 :                         pos = hostapd_eid_country_add(pos, end, chan_spacing,
     258             :                                                       start, prev);
     259          26 :                         start = NULL;
     260             :                 }
     261             : 
     262             :                 /* Start new group */
     263          61 :                 start = prev = chan;
     264             :         }
     265             : 
     266          35 :         if (start) {
     267          35 :                 pos = hostapd_eid_country_add(pos, end, chan_spacing,
     268             :                                               start, prev);
     269             :         }
     270             : 
     271          35 :         if ((pos - eid) & 1) {
     272          26 :                 if (end - pos < 1)
     273           0 :                         return eid;
     274          26 :                 *pos++ = 0; /* pad for 16-bit alignment */
     275             :         }
     276             : 
     277          35 :         eid[1] = (pos - eid) - 2;
     278             : 
     279          35 :         return pos;
     280             : }
     281             : 
     282             : 
     283        5053 : static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
     284             : {
     285             :         const u8 *ie;
     286             :         size_t ielen;
     287             : 
     288        5053 :         ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
     289        5053 :         if (ie == NULL || ielen > len)
     290        1212 :                 return eid;
     291             : 
     292        3841 :         os_memcpy(eid, ie, ielen);
     293        3841 :         return eid + ielen;
     294             : }
     295             : 
     296             : 
     297        5053 : static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
     298             : {
     299             :         u8 chan;
     300             : 
     301        5053 :         if (!hapd->cs_freq_params.freq)
     302        5030 :                 return eid;
     303             : 
     304          23 :         if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) ==
     305             :             NUM_HOSTAPD_MODES)
     306           0 :                 return eid;
     307             : 
     308          23 :         *eid++ = WLAN_EID_CHANNEL_SWITCH;
     309          23 :         *eid++ = 3;
     310          23 :         *eid++ = hapd->cs_block_tx;
     311          23 :         *eid++ = chan;
     312          23 :         *eid++ = hapd->cs_count;
     313             : 
     314          23 :         return eid;
     315             : }
     316             : 
     317             : 
     318          23 : static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
     319             : {
     320             :         u8 sec_ch;
     321             : 
     322          23 :         if (!hapd->cs_freq_params.sec_channel_offset)
     323          14 :                 return eid;
     324             : 
     325           9 :         if (hapd->cs_freq_params.sec_channel_offset == -1)
     326           2 :                 sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
     327           7 :         else if (hapd->cs_freq_params.sec_channel_offset == 1)
     328           6 :                 sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
     329             :         else
     330           1 :                 return eid;
     331             : 
     332           8 :         *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
     333           8 :         *eid++ = 1;
     334           8 :         *eid++ = sec_ch;
     335             : 
     336           8 :         return eid;
     337             : }
     338             : 
     339             : 
     340        5053 : static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
     341             :                                   u8 *start, unsigned int *csa_counter_off)
     342             : {
     343        5053 :         u8 *old_pos = pos;
     344             : 
     345        5053 :         if (!csa_counter_off)
     346           0 :                 return pos;
     347             : 
     348        5053 :         *csa_counter_off = 0;
     349        5053 :         pos = hostapd_eid_csa(hapd, pos);
     350             : 
     351        5053 :         if (pos != old_pos) {
     352             :                 /* save an offset to the counter - should be last byte */
     353          23 :                 *csa_counter_off = pos - start - 1;
     354          23 :                 pos = hostapd_eid_secondary_channel(hapd, pos);
     355             :         }
     356             : 
     357        5053 :         return pos;
     358             : }
     359             : 
     360             : 
     361        2311 : static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
     362             :                                    struct sta_info *sta,
     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        2311 :         buflen = MAX_PROBERESP_LEN;
     372             : #ifdef CONFIG_WPS
     373        2311 :         if (hapd->wps_probe_resp_ie)
     374         633 :                 buflen += wpabuf_len(hapd->wps_probe_resp_ie);
     375             : #endif /* CONFIG_WPS */
     376             : #ifdef CONFIG_P2P
     377         363 :         if (hapd->p2p_probe_resp_ie)
     378         339 :                 buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
     379             : #endif /* CONFIG_P2P */
     380        2311 :         if (hapd->conf->vendor_elements)
     381           1 :                 buflen += wpabuf_len(hapd->conf->vendor_elements);
     382        2311 :         if (hapd->conf->vendor_vht) {
     383           2 :                 buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
     384             :                         2 + sizeof(struct ieee80211_vht_operation);
     385             :         }
     386        2311 :         resp = os_zalloc(buflen);
     387        2311 :         if (resp == NULL)
     388           0 :                 return NULL;
     389             : 
     390        2311 :         epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
     391             : 
     392        2311 :         resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     393             :                                            WLAN_FC_STYPE_PROBE_RESP);
     394        2311 :         if (req)
     395        2311 :                 os_memcpy(resp->da, req->sa, ETH_ALEN);
     396        2311 :         os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
     397             : 
     398        2311 :         os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
     399        2311 :         resp->u.probe_resp.beacon_int =
     400        2311 :                 host_to_le16(hapd->iconf->beacon_int);
     401             : 
     402             :         /* hardware or low-level driver will setup seq_ctrl and timestamp */
     403        2311 :         resp->u.probe_resp.capab_info =
     404        2311 :                 host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
     405             : 
     406        2311 :         pos = resp->u.probe_resp.variable;
     407        2311 :         *pos++ = WLAN_EID_SSID;
     408        2311 :         *pos++ = hapd->conf->ssid.ssid_len;
     409        2311 :         os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
     410        2311 :         pos += hapd->conf->ssid.ssid_len;
     411             : 
     412             :         /* Supported rates */
     413        2311 :         pos = hostapd_eid_supp_rates(hapd, pos);
     414             : 
     415             :         /* DS Params */
     416        2311 :         pos = hostapd_eid_ds_params(hapd, pos);
     417             : 
     418        2311 :         pos = hostapd_eid_country(hapd, pos, epos - pos);
     419             : 
     420             :         /* Power Constraint element */
     421        2311 :         pos = hostapd_eid_pwr_constraint(hapd, pos);
     422             : 
     423             :         /* ERP Information element */
     424        2311 :         pos = hostapd_eid_erp_info(hapd, pos);
     425             : 
     426             :         /* Extended supported rates */
     427        2311 :         pos = hostapd_eid_ext_supp_rates(hapd, pos);
     428             : 
     429             :         /* RSN, MDIE, WPA */
     430        2311 :         pos = hostapd_eid_wpa(hapd, pos, epos - pos);
     431             : 
     432        2311 :         pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
     433             : 
     434        2311 :         pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
     435             : 
     436             : #ifdef CONFIG_IEEE80211N
     437        2311 :         pos = hostapd_eid_ht_capabilities(hapd, pos);
     438        2311 :         pos = hostapd_eid_ht_operation(hapd, pos);
     439             : #endif /* CONFIG_IEEE80211N */
     440             : 
     441        2311 :         pos = hostapd_eid_ext_capab(hapd, pos);
     442             : 
     443        2311 :         pos = hostapd_eid_time_adv(hapd, pos);
     444        2311 :         pos = hostapd_eid_time_zone(hapd, pos);
     445             : 
     446        2311 :         pos = hostapd_eid_interworking(hapd, pos);
     447        2311 :         pos = hostapd_eid_adv_proto(hapd, pos);
     448        2311 :         pos = hostapd_eid_roaming_consortium(hapd, pos);
     449             : 
     450        2311 :         pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
     451             :                                     &hapd->cs_c_off_proberesp);
     452             : #ifdef CONFIG_IEEE80211AC
     453        1948 :         if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
     454          13 :                 pos = hostapd_eid_vht_capabilities(hapd, pos);
     455          13 :                 pos = hostapd_eid_vht_operation(hapd, pos);
     456             :         }
     457        1948 :         if (hapd->conf->vendor_vht)
     458           2 :                 pos = hostapd_eid_vendor_vht(hapd, pos);
     459             : #endif /* CONFIG_IEEE80211AC */
     460             : 
     461             :         /* Wi-Fi Alliance WMM */
     462        2311 :         pos = hostapd_eid_wmm(hapd, pos);
     463             : 
     464             : #ifdef CONFIG_WPS
     465        2311 :         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
     466         633 :                 os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
     467             :                           wpabuf_len(hapd->wps_probe_resp_ie));
     468         633 :                 pos += wpabuf_len(hapd->wps_probe_resp_ie);
     469             :         }
     470             : #endif /* CONFIG_WPS */
     471             : 
     472             : #ifdef CONFIG_P2P
     473         673 :         if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
     474         310 :             hapd->p2p_probe_resp_ie) {
     475         310 :                 os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
     476             :                           wpabuf_len(hapd->p2p_probe_resp_ie));
     477         310 :                 pos += wpabuf_len(hapd->p2p_probe_resp_ie);
     478             :         }
     479             : #endif /* CONFIG_P2P */
     480             : #ifdef CONFIG_P2P_MANAGER
     481        1948 :         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
     482             :             P2P_MANAGE)
     483           6 :                 pos = hostapd_eid_p2p_manage(hapd, pos);
     484             : #endif /* CONFIG_P2P_MANAGER */
     485             : 
     486             : #ifdef CONFIG_HS20
     487        2311 :         pos = hostapd_eid_hs20_indication(hapd, pos);
     488        2311 :         pos = hostapd_eid_osen(hapd, pos);
     489             : #endif /* CONFIG_HS20 */
     490             : 
     491        2311 :         if (hapd->conf->vendor_elements) {
     492           1 :                 os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
     493             :                           wpabuf_len(hapd->conf->vendor_elements));
     494           1 :                 pos += wpabuf_len(hapd->conf->vendor_elements);
     495             :         }
     496             : 
     497        2311 :         *resp_len = pos - (u8 *) resp;
     498        2311 :         return (u8 *) resp;
     499             : }
     500             : 
     501             : 
     502             : enum ssid_match_result {
     503             :         NO_SSID_MATCH,
     504             :         EXACT_SSID_MATCH,
     505             :         WILDCARD_SSID_MATCH
     506             : };
     507             : 
     508        2444 : static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
     509             :                                          const u8 *ssid, size_t ssid_len,
     510             :                                          const u8 *ssid_list,
     511             :                                          size_t ssid_list_len)
     512             : {
     513             :         const u8 *pos, *end;
     514        2444 :         int wildcard = 0;
     515             : 
     516        2444 :         if (ssid_len == 0)
     517        1927 :                 wildcard = 1;
     518        2870 :         if (ssid_len == hapd->conf->ssid.ssid_len &&
     519         426 :             os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
     520         402 :                 return EXACT_SSID_MATCH;
     521             : 
     522        2042 :         if (ssid_list == NULL)
     523        2042 :                 return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
     524             : 
     525           0 :         pos = ssid_list;
     526           0 :         end = ssid_list + ssid_list_len;
     527           0 :         while (pos + 1 <= end) {
     528           0 :                 if (pos + 2 + pos[1] > end)
     529           0 :                         break;
     530           0 :                 if (pos[1] == 0)
     531           0 :                         wildcard = 1;
     532           0 :                 if (pos[1] == hapd->conf->ssid.ssid_len &&
     533           0 :                     os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
     534           0 :                         return EXACT_SSID_MATCH;
     535           0 :                 pos += 2 + pos[1];
     536             :         }
     537             : 
     538           0 :         return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
     539             : }
     540             : 
     541             : 
     542        2471 : void handle_probe_req(struct hostapd_data *hapd,
     543             :                       const struct ieee80211_mgmt *mgmt, size_t len,
     544             :                       int ssi_signal)
     545             : {
     546             :         u8 *resp;
     547             :         struct ieee802_11_elems elems;
     548             :         const u8 *ie;
     549             :         size_t ie_len;
     550        2471 :         struct sta_info *sta = NULL;
     551             :         size_t i, resp_len;
     552             :         int noack;
     553             :         enum ssid_match_result res;
     554             : 
     555        2471 :         ie = mgmt->u.probe_req.variable;
     556        2471 :         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
     557         160 :                 return;
     558        2471 :         ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
     559             : 
     560        3504 :         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
     561        2066 :                 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
     562        1033 :                                             mgmt->sa, mgmt->da, mgmt->bssid,
     563             :                                             ie, ie_len, ssi_signal) > 0)
     564           0 :                         return;
     565             : 
     566        2471 :         if (!hapd->iconf->send_probe_response)
     567           0 :                 return;
     568             : 
     569        2471 :         if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
     570           0 :                 wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
     571           0 :                            MAC2STR(mgmt->sa));
     572           0 :                 return;
     573             :         }
     574             : 
     575        2471 :         if ((!elems.ssid || !elems.supp_rates)) {
     576           0 :                 wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
     577             :                            "without SSID or supported rates element",
     578           0 :                            MAC2STR(mgmt->sa));
     579           0 :                 return;
     580             :         }
     581             : 
     582             : #ifdef CONFIG_P2P
     583         378 :         if (hapd->p2p && elems.wps_ie) {
     584             :                 struct wpabuf *wps;
     585         343 :                 wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
     586         343 :                 if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
     587           3 :                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
     588             :                                    "due to mismatch with Requested Device "
     589             :                                    "Type");
     590           3 :                         wpabuf_free(wps);
     591           3 :                         return;
     592             :                 }
     593         340 :                 wpabuf_free(wps);
     594             :         }
     595             : 
     596         375 :         if (hapd->p2p && elems.p2p) {
     597             :                 struct wpabuf *p2p;
     598         338 :                 p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
     599         338 :                 if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
     600           3 :                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
     601             :                                    "due to mismatch with Device ID");
     602           3 :                         wpabuf_free(p2p);
     603           3 :                         return;
     604             :                 }
     605         335 :                 wpabuf_free(p2p);
     606             :         }
     607             : #endif /* CONFIG_P2P */
     608             : 
     609        2486 :         if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
     610          21 :             elems.ssid_list_len == 0) {
     611         126 :                 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
     612         126 :                            "broadcast SSID ignored", MAC2STR(mgmt->sa));
     613          21 :                 return;
     614             :         }
     615             : 
     616        2444 :         sta = ap_get_sta(hapd, mgmt->sa);
     617             : 
     618             : #ifdef CONFIG_P2P
     619         720 :         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
     620         464 :             elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
     621         116 :             os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
     622             :                       P2P_WILDCARD_SSID_LEN) == 0) {
     623             :                 /* Process P2P Wildcard SSID like Wildcard SSID */
     624         116 :                 elems.ssid_len = 0;
     625             :         }
     626             : #endif /* CONFIG_P2P */
     627             : 
     628        2444 :         res = ssid_match(hapd, elems.ssid, elems.ssid_len,
     629        2444 :                          elems.ssid_list, elems.ssid_list_len);
     630        2444 :         if (res != NO_SSID_MATCH) {
     631        2329 :                 if (sta)
     632         274 :                         sta->ssid_probe = &hapd->conf->ssid;
     633             :         } else {
     634         115 :                 if (!(mgmt->da[0] & 0x01)) {
     635           0 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     636             :                                    " for foreign SSID '%s' (DA " MACSTR ")%s",
     637           0 :                                    MAC2STR(mgmt->sa),
     638           0 :                                    wpa_ssid_txt(elems.ssid, elems.ssid_len),
     639           0 :                                    MAC2STR(mgmt->da),
     640           0 :                                    elems.ssid_list ? " (SSID list)" : "");
     641             :                 }
     642         115 :                 return;
     643             :         }
     644             : 
     645             : #ifdef CONFIG_INTERWORKING
     646        2641 :         if (hapd->conf->interworking &&
     647         590 :             elems.interworking && elems.interworking_len >= 1) {
     648         278 :                 u8 ant = elems.interworking[0] & 0x0f;
     649         288 :                 if (ant != INTERWORKING_ANT_WILDCARD &&
     650          10 :                     ant != hapd->conf->access_network_type) {
     651          35 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     652             :                                    " for mismatching ANT %u ignored",
     653          30 :                                    MAC2STR(mgmt->sa), ant);
     654           5 :                         return;
     655             :                 }
     656             :         }
     657             : 
     658        2597 :         if (hapd->conf->interworking && elems.interworking &&
     659         541 :             (elems.interworking_len == 7 || elems.interworking_len == 9)) {
     660             :                 const u8 *hessid;
     661           5 :                 if (elems.interworking_len == 7)
     662           5 :                         hessid = elems.interworking + 1;
     663             :                 else
     664           0 :                         hessid = elems.interworking + 1 + 2;
     665          10 :                 if (!is_broadcast_ether_addr(hessid) &&
     666           5 :                     os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
     667          36 :                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
     668             :                                    " for mismatching HESSID " MACSTR
     669             :                                    " ignored",
     670          36 :                                    MAC2STR(mgmt->sa), MAC2STR(hessid));
     671           3 :                         return;
     672             :                 }
     673             :         }
     674             : #endif /* CONFIG_INTERWORKING */
     675             : 
     676             : #ifdef CONFIG_P2P
     677         702 :         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
     678         339 :             supp_rates_11b_only(&elems)) {
     679             :                 /* Indicates support for 11b rates only */
     680           0 :                 wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
     681             :                            MACSTR " with only 802.11b rates",
     682           0 :                            MAC2STR(mgmt->sa));
     683           0 :                 return;
     684             :         }
     685             : #endif /* CONFIG_P2P */
     686             : 
     687             :         /* TODO: verify that supp_rates contains at least one matching rate
     688             :          * with AP configuration */
     689             : 
     690             : #ifdef CONFIG_TESTING_OPTIONS
     691        2334 :         if (hapd->iconf->ignore_probe_probability > 0.0 &&
     692          13 :             drand48() < hapd->iconf->ignore_probe_probability) {
     693          60 :                 wpa_printf(MSG_INFO,
     694             :                            "TESTING: ignoring probe request from " MACSTR,
     695          60 :                            MAC2STR(mgmt->sa));
     696          10 :                 return;
     697             :         }
     698             : #endif /* CONFIG_TESTING_OPTIONS */
     699             : 
     700        2311 :         resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
     701             :                                       &resp_len);
     702        2311 :         if (resp == NULL)
     703           0 :                 return;
     704             : 
     705             :         /*
     706             :          * If this is a broadcast probe request, apply no ack policy to avoid
     707             :          * excessive retries.
     708             :          */
     709        4227 :         noack = !!(res == WILDCARD_SSID_MATCH &&
     710        1916 :                    is_broadcast_ether_addr(mgmt->da));
     711             : 
     712        2311 :         if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
     713           4 :                 wpa_printf(MSG_INFO, "handle_probe_req: send failed");
     714             : 
     715        2311 :         os_free(resp);
     716             : 
     717       16177 :         wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
     718       13866 :                    "SSID", MAC2STR(mgmt->sa),
     719        2311 :                    elems.ssid_len == 0 ? "broadcast" : "our");
     720             : }
     721             : 
     722             : 
     723        2742 : static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
     724             :                                         size_t *resp_len)
     725             : {
     726             :         /* check probe response offloading caps and print warnings */
     727        2742 :         if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
     728        2742 :                 return NULL;
     729             : 
     730             : #ifdef CONFIG_WPS
     731           0 :         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
     732           0 :             (!(hapd->iface->probe_resp_offloads &
     733             :                (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
     734             :                 WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
     735           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
     736             :                            "Probe Response while not supporting this");
     737             : #endif /* CONFIG_WPS */
     738             : 
     739             : #ifdef CONFIG_P2P
     740           0 :         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
     741           0 :             !(hapd->iface->probe_resp_offloads &
     742             :               WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
     743           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
     744             :                            "Probe Response while not supporting this");
     745             : #endif  /* CONFIG_P2P */
     746             : 
     747           0 :         if (hapd->conf->interworking &&
     748           0 :             !(hapd->iface->probe_resp_offloads &
     749             :               WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
     750           0 :                 wpa_printf(MSG_WARNING, "Device is trying to offload "
     751             :                            "Interworking Probe Response while not supporting "
     752             :                            "this");
     753             : 
     754             :         /* Generate a Probe Response template for the non-P2P case */
     755           0 :         return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
     756             : }
     757             : 
     758             : #endif /* NEED_AP_MLME */
     759             : 
     760             : 
     761        2744 : int ieee802_11_build_ap_params(struct hostapd_data *hapd,
     762             :                                struct wpa_driver_ap_params *params)
     763             : {
     764        2744 :         struct ieee80211_mgmt *head = NULL;
     765        2744 :         u8 *tail = NULL;
     766        2744 :         size_t head_len = 0, tail_len = 0;
     767        2744 :         u8 *resp = NULL;
     768        2744 :         size_t resp_len = 0;
     769             : #ifdef NEED_AP_MLME
     770             :         u16 capab_info;
     771             :         u8 *pos, *tailpos;
     772             : 
     773             : #define BEACON_HEAD_BUF_SIZE 256
     774             : #define BEACON_TAIL_BUF_SIZE 512
     775        2744 :         head = os_zalloc(BEACON_HEAD_BUF_SIZE);
     776        2744 :         tail_len = BEACON_TAIL_BUF_SIZE;
     777             : #ifdef CONFIG_WPS
     778        2744 :         if (hapd->conf->wps_state && hapd->wps_beacon_ie)
     779        1698 :                 tail_len += wpabuf_len(hapd->wps_beacon_ie);
     780             : #endif /* CONFIG_WPS */
     781             : #ifdef CONFIG_P2P
     782        1402 :         if (hapd->p2p_beacon_ie)
     783        1376 :                 tail_len += wpabuf_len(hapd->p2p_beacon_ie);
     784             : #endif /* CONFIG_P2P */
     785        2744 :         if (hapd->conf->vendor_elements)
     786           1 :                 tail_len += wpabuf_len(hapd->conf->vendor_elements);
     787             : 
     788             : #ifdef CONFIG_IEEE80211AC
     789        1342 :         if (hapd->conf->vendor_vht) {
     790           1 :                 tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
     791             :                         2 + sizeof(struct ieee80211_vht_operation);
     792             :         }
     793             : #endif /* CONFIG_IEEE80211AC */
     794             : 
     795        2744 :         tailpos = tail = os_malloc(tail_len);
     796        2744 :         if (head == NULL || tail == NULL) {
     797           2 :                 wpa_printf(MSG_ERROR, "Failed to set beacon data");
     798           2 :                 os_free(head);
     799           2 :                 os_free(tail);
     800           2 :                 return -1;
     801             :         }
     802             : 
     803        2742 :         head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
     804             :                                            WLAN_FC_STYPE_BEACON);
     805        2742 :         head->duration = host_to_le16(0);
     806        2742 :         os_memset(head->da, 0xff, ETH_ALEN);
     807             : 
     808        2742 :         os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
     809        2742 :         os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
     810        2742 :         head->u.beacon.beacon_int =
     811        2742 :                 host_to_le16(hapd->iconf->beacon_int);
     812             : 
     813             :         /* hardware or low-level driver will setup seq_ctrl and timestamp */
     814        2742 :         capab_info = hostapd_own_capab_info(hapd, NULL, 0);
     815        2742 :         head->u.beacon.capab_info = host_to_le16(capab_info);
     816        2742 :         pos = &head->u.beacon.variable[0];
     817             : 
     818             :         /* SSID */
     819        2742 :         *pos++ = WLAN_EID_SSID;
     820        2742 :         if (hapd->conf->ignore_broadcast_ssid == 2) {
     821             :                 /* clear the data, but keep the correct length of the SSID */
     822           1 :                 *pos++ = hapd->conf->ssid.ssid_len;
     823           1 :                 os_memset(pos, 0, hapd->conf->ssid.ssid_len);
     824           1 :                 pos += hapd->conf->ssid.ssid_len;
     825        2741 :         } else if (hapd->conf->ignore_broadcast_ssid) {
     826           8 :                 *pos++ = 0; /* empty SSID */
     827             :         } else {
     828        2733 :                 *pos++ = hapd->conf->ssid.ssid_len;
     829        2733 :                 os_memcpy(pos, hapd->conf->ssid.ssid,
     830             :                           hapd->conf->ssid.ssid_len);
     831        2733 :                 pos += hapd->conf->ssid.ssid_len;
     832             :         }
     833             : 
     834             :         /* Supported rates */
     835        2742 :         pos = hostapd_eid_supp_rates(hapd, pos);
     836             : 
     837             :         /* DS Params */
     838        2742 :         pos = hostapd_eid_ds_params(hapd, pos);
     839             : 
     840        2742 :         head_len = pos - (u8 *) head;
     841             : 
     842        2742 :         tailpos = hostapd_eid_country(hapd, tailpos,
     843        2742 :                                       tail + BEACON_TAIL_BUF_SIZE - tailpos);
     844             : 
     845             :         /* Power Constraint element */
     846        2742 :         tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
     847             : 
     848             :         /* ERP Information element */
     849        2742 :         tailpos = hostapd_eid_erp_info(hapd, tailpos);
     850             : 
     851             :         /* Extended supported rates */
     852        2742 :         tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
     853             : 
     854             :         /* RSN, MDIE, WPA */
     855        2742 :         tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
     856             :                                   tailpos);
     857             : 
     858        2742 :         tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
     859        2742 :                                                tail + BEACON_TAIL_BUF_SIZE -
     860             :                                                tailpos);
     861             : 
     862        2742 :         tailpos = hostapd_eid_bss_load(hapd, tailpos,
     863        2742 :                                        tail + BEACON_TAIL_BUF_SIZE - tailpos);
     864             : 
     865             : #ifdef CONFIG_IEEE80211N
     866        2742 :         tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
     867        2742 :         tailpos = hostapd_eid_ht_operation(hapd, tailpos);
     868             : #endif /* CONFIG_IEEE80211N */
     869             : 
     870        2742 :         tailpos = hostapd_eid_ext_capab(hapd, tailpos);
     871             : 
     872             :         /*
     873             :          * TODO: Time Advertisement element should only be included in some
     874             :          * DTIM Beacon frames.
     875             :          */
     876        2742 :         tailpos = hostapd_eid_time_adv(hapd, tailpos);
     877             : 
     878        2742 :         tailpos = hostapd_eid_interworking(hapd, tailpos);
     879        2742 :         tailpos = hostapd_eid_adv_proto(hapd, tailpos);
     880        2742 :         tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
     881        2742 :         tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
     882             :                                         &hapd->cs_c_off_beacon);
     883             : #ifdef CONFIG_IEEE80211AC
     884        1340 :         if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
     885          16 :                 tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
     886          16 :                 tailpos = hostapd_eid_vht_operation(hapd, tailpos);
     887             :         }
     888        1340 :         if (hapd->conf->vendor_vht)
     889           1 :                 tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
     890             : #endif /* CONFIG_IEEE80211AC */
     891             : 
     892             :         /* Wi-Fi Alliance WMM */
     893        2742 :         tailpos = hostapd_eid_wmm(hapd, tailpos);
     894             : 
     895             : #ifdef CONFIG_WPS
     896        2742 :         if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
     897        1698 :                 os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
     898             :                           wpabuf_len(hapd->wps_beacon_ie));
     899        1698 :                 tailpos += wpabuf_len(hapd->wps_beacon_ie);
     900             :         }
     901             : #endif /* CONFIG_WPS */
     902             : 
     903             : #ifdef CONFIG_P2P
     904        1402 :         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
     905        1376 :                 os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
     906             :                           wpabuf_len(hapd->p2p_beacon_ie));
     907        1376 :                 tailpos += wpabuf_len(hapd->p2p_beacon_ie);
     908             :         }
     909             : #endif /* CONFIG_P2P */
     910             : #ifdef CONFIG_P2P_MANAGER
     911        1340 :         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
     912             :             P2P_MANAGE)
     913           5 :                 tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
     914             : #endif /* CONFIG_P2P_MANAGER */
     915             : 
     916             : #ifdef CONFIG_HS20
     917        2742 :         tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
     918        2742 :         tailpos = hostapd_eid_osen(hapd, tailpos);
     919             : #endif /* CONFIG_HS20 */
     920             : 
     921        2742 :         if (hapd->conf->vendor_elements) {
     922           1 :                 os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
     923             :                           wpabuf_len(hapd->conf->vendor_elements));
     924           1 :                 tailpos += wpabuf_len(hapd->conf->vendor_elements);
     925             :         }
     926             : 
     927        2742 :         tail_len = tailpos > tail ? tailpos - tail : 0;
     928             : 
     929        2742 :         resp = hostapd_probe_resp_offloads(hapd, &resp_len);
     930             : #endif /* NEED_AP_MLME */
     931             : 
     932        2742 :         os_memset(params, 0, sizeof(*params));
     933        2742 :         params->head = (u8 *) head;
     934        2742 :         params->head_len = head_len;
     935        2742 :         params->tail = tail;
     936        2742 :         params->tail_len = tail_len;
     937        2742 :         params->proberesp = resp;
     938        2742 :         params->proberesp_len = resp_len;
     939        2742 :         params->dtim_period = hapd->conf->dtim_period;
     940        2742 :         params->beacon_int = hapd->iconf->beacon_int;
     941        2742 :         params->basic_rates = hapd->iface->basic_rates;
     942        2742 :         params->ssid = hapd->conf->ssid.ssid;
     943        2742 :         params->ssid_len = hapd->conf->ssid.ssid_len;
     944        5484 :         params->pairwise_ciphers = hapd->conf->wpa_pairwise |
     945        2742 :                 hapd->conf->rsn_pairwise;
     946        2742 :         params->group_cipher = hapd->conf->wpa_group;
     947        2742 :         params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
     948        2742 :         params->auth_algs = hapd->conf->auth_algs;
     949        2742 :         params->wpa_version = hapd->conf->wpa;
     950        5486 :         params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
     951         459 :                 (hapd->conf->ieee802_1x &&
     952           8 :                  (hapd->conf->default_wep_key_len ||
     953           3 :                   hapd->conf->individual_wep_key_len));
     954        2742 :         switch (hapd->conf->ignore_broadcast_ssid) {
     955             :         case 0:
     956        2733 :                 params->hide_ssid = NO_SSID_HIDING;
     957        2733 :                 break;
     958             :         case 1:
     959           8 :                 params->hide_ssid = HIDDEN_SSID_ZERO_LEN;
     960           8 :                 break;
     961             :         case 2:
     962           1 :                 params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
     963           1 :                 break;
     964             :         }
     965        2742 :         params->isolate = hapd->conf->isolate;
     966        2742 :         params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
     967             : #ifdef NEED_AP_MLME
     968        2742 :         params->cts_protect = !!(ieee802_11_erp_info(hapd) &
     969             :                                 ERP_INFO_USE_PROTECTION);
     970        5442 :         params->preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
     971        2700 :                 hapd->iconf->preamble == SHORT_PREAMBLE;
     972        5474 :         if (hapd->iface->current_mode &&
     973        2732 :             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
     974        2616 :                 params->short_slot_time =
     975        2616 :                         hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
     976             :         else
     977         126 :                 params->short_slot_time = -1;
     978        2742 :         if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
     979         125 :                 params->ht_opmode = -1;
     980             :         else
     981        2617 :                 params->ht_opmode = hapd->iface->ht_op_mode;
     982             : #endif /* NEED_AP_MLME */
     983        2742 :         params->interworking = hapd->conf->interworking;
     984        2861 :         if (hapd->conf->interworking &&
     985         119 :             !is_zero_ether_addr(hapd->conf->hessid))
     986          54 :                 params->hessid = hapd->conf->hessid;
     987        2742 :         params->access_network_type = hapd->conf->access_network_type;
     988        2742 :         params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
     989             : #ifdef CONFIG_HS20
     990        2742 :         params->disable_dgaf = hapd->conf->disable_dgaf;
     991        2742 :         if (hapd->conf->osen) {
     992           1 :                 params->privacy = 1;
     993           1 :                 params->osen = 1;
     994             :         }
     995             : #endif /* CONFIG_HS20 */
     996        2742 :         return 0;
     997             : }
     998             : 
     999             : 
    1000        2742 : void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
    1001             : {
    1002        2742 :         os_free(params->tail);
    1003        2742 :         params->tail = NULL;
    1004        2742 :         os_free(params->head);
    1005        2742 :         params->head = NULL;
    1006        2742 :         os_free(params->proberesp);
    1007        2742 :         params->proberesp = NULL;
    1008        2742 : }
    1009             : 
    1010             : 
    1011        2698 : int ieee802_11_set_beacon(struct hostapd_data *hapd)
    1012             : {
    1013             :         struct wpa_driver_ap_params params;
    1014             :         struct hostapd_freq_params freq;
    1015        2698 :         struct hostapd_iface *iface = hapd->iface;
    1016        2698 :         struct hostapd_config *iconf = iface->conf;
    1017             :         struct wpabuf *beacon, *proberesp, *assocresp;
    1018        2698 :         int res, ret = -1;
    1019             : 
    1020        2698 :         if (hapd->csa_in_progress) {
    1021           0 :                 wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
    1022           0 :                 return -1;
    1023             :         }
    1024             : 
    1025        2698 :         hapd->beacon_set_done = 1;
    1026             : 
    1027        2698 :         if (ieee802_11_build_ap_params(hapd, &params) < 0)
    1028           2 :                 return -1;
    1029             : 
    1030        2696 :         if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
    1031             :             0)
    1032           0 :                 goto fail;
    1033             : 
    1034        2696 :         params.beacon_ies = beacon;
    1035        2696 :         params.proberesp_ies = proberesp;
    1036        2696 :         params.assocresp_ies = assocresp;
    1037             : 
    1038        5382 :         if (iface->current_mode &&
    1039       13430 :             hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
    1040        2686 :                                     iconf->channel, iconf->ieee80211n,
    1041             :                                     iconf->ieee80211ac,
    1042             :                                     iconf->secondary_channel,
    1043        2686 :                                     iconf->vht_oper_chwidth,
    1044        2686 :                                     iconf->vht_oper_centr_freq_seg0_idx,
    1045        2686 :                                     iconf->vht_oper_centr_freq_seg1_idx,
    1046        2686 :                                     iface->current_mode->vht_capab) == 0)
    1047        2686 :                 params.freq = &freq;
    1048             : 
    1049        2696 :         res = hostapd_drv_set_ap(hapd, &params);
    1050        2696 :         hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
    1051        2696 :         if (res)
    1052           1 :                 wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
    1053             :         else
    1054        2695 :                 ret = 0;
    1055             : fail:
    1056        2696 :         ieee802_11_free_ap_params(&params);
    1057        2696 :         return ret;
    1058             : }
    1059             : 
    1060             : 
    1061         764 : int ieee802_11_set_beacons(struct hostapd_iface *iface)
    1062             : {
    1063             :         size_t i;
    1064         764 :         int ret = 0;
    1065             : 
    1066        1532 :         for (i = 0; i < iface->num_bss; i++) {
    1067        1536 :                 if (iface->bss[i]->started &&
    1068         768 :                     ieee802_11_set_beacon(iface->bss[i]) < 0)
    1069           0 :                         ret = -1;
    1070             :         }
    1071             : 
    1072         764 :         return ret;
    1073             : }
    1074             : 
    1075             : 
    1076             : /* only update beacons if started */
    1077           3 : int ieee802_11_update_beacons(struct hostapd_iface *iface)
    1078             : {
    1079             :         size_t i;
    1080           3 :         int ret = 0;
    1081             : 
    1082           6 :         for (i = 0; i < iface->num_bss; i++) {
    1083           6 :                 if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
    1084           3 :                     ieee802_11_set_beacon(iface->bss[i]) < 0)
    1085           0 :                         ret = -1;
    1086             :         }
    1087             : 
    1088           3 :         return ret;
    1089             : }
    1090             : 
    1091             : #endif /* CONFIG_NATIVE_WINDOWS */

Generated by: LCOV version 1.10