hostapd: Fix set beacon in multiple BSSID scenario
[mech_eap.git] / src / ap / beacon.c
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 program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16
17 #include "utils/includes.h"
18
19 #ifndef CONFIG_NATIVE_WINDOWS
20
21 #include "utils/common.h"
22 #include "common/ieee802_11_defs.h"
23 #include "common/ieee802_11_common.h"
24 #include "drivers/driver.h"
25 #include "wps/wps_defs.h"
26 #include "p2p/p2p.h"
27 #include "hostapd.h"
28 #include "ieee802_11.h"
29 #include "wpa_auth.h"
30 #include "wmm.h"
31 #include "ap_config.h"
32 #include "sta_info.h"
33 #include "p2p_hostapd.h"
34 #include "ap_drv_ops.h"
35 #include "beacon.h"
36 #include "hs20.h"
37
38
39 #ifdef NEED_AP_MLME
40
41 static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
42 {
43 #ifdef CONFIG_TESTING_OPTIONS
44         if (hapd->conf->bss_load_test_set) {
45                 if (2 + 5 > len)
46                         return eid;
47                 *eid++ = WLAN_EID_BSS_LOAD;
48                 *eid++ = 5;
49                 os_memcpy(eid, hapd->conf->bss_load_test, 5);
50                 eid += 5;
51         }
52 #endif /* CONFIG_TESTING_OPTIONS */
53         return eid;
54 }
55
56
57 static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
58 {
59         u8 erp = 0;
60
61         if (hapd->iface->current_mode == NULL ||
62             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
63                 return 0;
64
65         if (hapd->iface->olbc)
66                 erp |= ERP_INFO_USE_PROTECTION;
67         if (hapd->iface->num_sta_non_erp > 0) {
68                 erp |= ERP_INFO_NON_ERP_PRESENT |
69                         ERP_INFO_USE_PROTECTION;
70         }
71         if (hapd->iface->num_sta_no_short_preamble > 0 ||
72             hapd->iconf->preamble == LONG_PREAMBLE)
73                 erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
74
75         return erp;
76 }
77
78
79 static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
80 {
81         *eid++ = WLAN_EID_DS_PARAMS;
82         *eid++ = 1;
83         *eid++ = hapd->iconf->channel;
84         return eid;
85 }
86
87
88 static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
89 {
90         if (hapd->iface->current_mode == NULL ||
91             hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
92                 return eid;
93
94         /* Set NonERP_present and use_protection bits if there
95          * are any associated NonERP stations. */
96         /* TODO: use_protection bit can be set to zero even if
97          * there are NonERP stations present. This optimization
98          * might be useful if NonERP stations are "quiet".
99          * See 802.11g/D6 E-1 for recommended practice.
100          * In addition, Non ERP present might be set, if AP detects Non ERP
101          * operation on other APs. */
102
103         /* Add ERP Information element */
104         *eid++ = WLAN_EID_ERP_INFO;
105         *eid++ = 1;
106         *eid++ = ieee802_11_erp_info(hapd);
107
108         return eid;
109 }
110
111
112 static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
113                                     struct hostapd_channel_data *start,
114                                     struct hostapd_channel_data *prev)
115 {
116         if (end - pos < 3)
117                 return pos;
118
119         /* first channel number */
120         *pos++ = start->chan;
121         /* number of channels */
122         *pos++ = (prev->chan - start->chan) / chan_spacing + 1;
123         /* maximum transmit power level */
124         *pos++ = start->max_tx_power;
125
126         return pos;
127 }
128
129
130 static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
131                                 int max_len)
132 {
133         u8 *pos = eid;
134         u8 *end = eid + max_len;
135         int i;
136         struct hostapd_hw_modes *mode;
137         struct hostapd_channel_data *start, *prev;
138         int chan_spacing = 1;
139
140         if (!hapd->iconf->ieee80211d || max_len < 6 ||
141             hapd->iface->current_mode == NULL)
142                 return eid;
143
144         *pos++ = WLAN_EID_COUNTRY;
145         pos++; /* length will be set later */
146         os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
147         pos += 3;
148
149         mode = hapd->iface->current_mode;
150         if (mode->mode == HOSTAPD_MODE_IEEE80211A)
151                 chan_spacing = 4;
152
153         start = prev = NULL;
154         for (i = 0; i < mode->num_channels; i++) {
155                 struct hostapd_channel_data *chan = &mode->channels[i];
156                 if (chan->flag & HOSTAPD_CHAN_DISABLED)
157                         continue;
158                 if (start && prev &&
159                     prev->chan + chan_spacing == chan->chan &&
160                     start->max_tx_power == chan->max_tx_power) {
161                         prev = chan;
162                         continue; /* can use same entry */
163                 }
164
165                 if (start) {
166                         pos = hostapd_eid_country_add(pos, end, chan_spacing,
167                                                       start, prev);
168                         start = NULL;
169                 }
170
171                 /* Start new group */
172                 start = prev = chan;
173         }
174
175         if (start) {
176                 pos = hostapd_eid_country_add(pos, end, chan_spacing,
177                                               start, prev);
178         }
179
180         if ((pos - eid) & 1) {
181                 if (end - pos < 1)
182                         return eid;
183                 *pos++ = 0; /* pad for 16-bit alignment */
184         }
185
186         eid[1] = (pos - eid) - 2;
187
188         return pos;
189 }
190
191
192 static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
193 {
194         const u8 *ie;
195         size_t ielen;
196
197         ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
198         if (ie == NULL || ielen > len)
199                 return eid;
200
201         os_memcpy(eid, ie, ielen);
202         return eid + ielen;
203 }
204
205
206 static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
207 {
208         u8 chan;
209
210         if (!hapd->iface->cs_freq)
211                 return eid;
212
213         if (ieee80211_freq_to_chan(hapd->iface->cs_freq, &chan) ==
214             NUM_HOSTAPD_MODES)
215                 return eid;
216
217         *eid++ = WLAN_EID_CHANNEL_SWITCH;
218         *eid++ = 3;
219         *eid++ = hapd->iface->cs_block_tx;
220         *eid++ = chan;
221         *eid++ = hapd->iface->cs_count;
222
223         return eid;
224 }
225
226
227 static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
228                                    struct sta_info *sta,
229                                    const struct ieee80211_mgmt *req,
230                                    int is_p2p, size_t *resp_len)
231 {
232         struct ieee80211_mgmt *resp;
233         u8 *pos, *epos, *old_pos;
234         size_t buflen;
235
236 #define MAX_PROBERESP_LEN 768
237         buflen = MAX_PROBERESP_LEN;
238 #ifdef CONFIG_WPS
239         if (hapd->wps_probe_resp_ie)
240                 buflen += wpabuf_len(hapd->wps_probe_resp_ie);
241 #endif /* CONFIG_WPS */
242 #ifdef CONFIG_P2P
243         if (hapd->p2p_probe_resp_ie)
244                 buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
245 #endif /* CONFIG_P2P */
246         if (hapd->conf->vendor_elements)
247                 buflen += wpabuf_len(hapd->conf->vendor_elements);
248         resp = os_zalloc(buflen);
249         if (resp == NULL)
250                 return NULL;
251
252         epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
253
254         resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
255                                            WLAN_FC_STYPE_PROBE_RESP);
256         if (req)
257                 os_memcpy(resp->da, req->sa, ETH_ALEN);
258         os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
259
260         os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
261         resp->u.probe_resp.beacon_int =
262                 host_to_le16(hapd->iconf->beacon_int);
263
264         /* hardware or low-level driver will setup seq_ctrl and timestamp */
265         resp->u.probe_resp.capab_info =
266                 host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
267
268         pos = resp->u.probe_resp.variable;
269         *pos++ = WLAN_EID_SSID;
270         *pos++ = hapd->conf->ssid.ssid_len;
271         os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
272         pos += hapd->conf->ssid.ssid_len;
273
274         /* Supported rates */
275         pos = hostapd_eid_supp_rates(hapd, pos);
276
277         /* DS Params */
278         pos = hostapd_eid_ds_params(hapd, pos);
279
280         pos = hostapd_eid_country(hapd, pos, epos - pos);
281
282         /* ERP Information element */
283         pos = hostapd_eid_erp_info(hapd, pos);
284
285         /* Extended supported rates */
286         pos = hostapd_eid_ext_supp_rates(hapd, pos);
287
288         /* RSN, MDIE, WPA */
289         pos = hostapd_eid_wpa(hapd, pos, epos - pos);
290
291         pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
292
293 #ifdef CONFIG_IEEE80211N
294         pos = hostapd_eid_ht_capabilities(hapd, pos);
295         pos = hostapd_eid_ht_operation(hapd, pos);
296 #endif /* CONFIG_IEEE80211N */
297
298         pos = hostapd_eid_ext_capab(hapd, pos);
299
300         pos = hostapd_eid_time_adv(hapd, pos);
301         pos = hostapd_eid_time_zone(hapd, pos);
302
303         pos = hostapd_eid_interworking(hapd, pos);
304         pos = hostapd_eid_adv_proto(hapd, pos);
305         pos = hostapd_eid_roaming_consortium(hapd, pos);
306
307         old_pos = pos;
308         pos = hostapd_eid_csa(hapd, pos);
309
310         /* save an offset to the counter - should be last byte */
311         hapd->iface->cs_c_off_proberesp = (pos != old_pos) ?
312                 pos - (u8 *) resp - 1 : 0;
313
314 #ifdef CONFIG_IEEE80211AC
315         pos = hostapd_eid_vht_capabilities(hapd, pos);
316         pos = hostapd_eid_vht_operation(hapd, pos);
317 #endif /* CONFIG_IEEE80211AC */
318
319         /* Wi-Fi Alliance WMM */
320         pos = hostapd_eid_wmm(hapd, pos);
321
322 #ifdef CONFIG_WPS
323         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
324                 os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
325                           wpabuf_len(hapd->wps_probe_resp_ie));
326                 pos += wpabuf_len(hapd->wps_probe_resp_ie);
327         }
328 #endif /* CONFIG_WPS */
329
330 #ifdef CONFIG_P2P
331         if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
332             hapd->p2p_probe_resp_ie) {
333                 os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
334                           wpabuf_len(hapd->p2p_probe_resp_ie));
335                 pos += wpabuf_len(hapd->p2p_probe_resp_ie);
336         }
337 #endif /* CONFIG_P2P */
338 #ifdef CONFIG_P2P_MANAGER
339         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
340             P2P_MANAGE)
341                 pos = hostapd_eid_p2p_manage(hapd, pos);
342 #endif /* CONFIG_P2P_MANAGER */
343
344 #ifdef CONFIG_HS20
345         pos = hostapd_eid_hs20_indication(hapd, pos);
346 #endif /* CONFIG_HS20 */
347
348         if (hapd->conf->vendor_elements) {
349                 os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
350                           wpabuf_len(hapd->conf->vendor_elements));
351                 pos += wpabuf_len(hapd->conf->vendor_elements);
352         }
353
354         *resp_len = pos - (u8 *) resp;
355         return (u8 *) resp;
356 }
357
358
359 enum ssid_match_result {
360         NO_SSID_MATCH,
361         EXACT_SSID_MATCH,
362         WILDCARD_SSID_MATCH
363 };
364
365 static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
366                                          const u8 *ssid, size_t ssid_len,
367                                          const u8 *ssid_list,
368                                          size_t ssid_list_len)
369 {
370         const u8 *pos, *end;
371         int wildcard = 0;
372
373         if (ssid_len == 0)
374                 wildcard = 1;
375         if (ssid_len == hapd->conf->ssid.ssid_len &&
376             os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
377                 return EXACT_SSID_MATCH;
378
379         if (ssid_list == NULL)
380                 return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
381
382         pos = ssid_list;
383         end = ssid_list + ssid_list_len;
384         while (pos + 1 <= end) {
385                 if (pos + 2 + pos[1] > end)
386                         break;
387                 if (pos[1] == 0)
388                         wildcard = 1;
389                 if (pos[1] == hapd->conf->ssid.ssid_len &&
390                     os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
391                         return EXACT_SSID_MATCH;
392                 pos += 2 + pos[1];
393         }
394
395         return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
396 }
397
398
399 void handle_probe_req(struct hostapd_data *hapd,
400                       const struct ieee80211_mgmt *mgmt, size_t len,
401                       int ssi_signal)
402 {
403         u8 *resp;
404         struct ieee802_11_elems elems;
405         const u8 *ie;
406         size_t ie_len;
407         struct sta_info *sta = NULL;
408         size_t i, resp_len;
409         int noack;
410         enum ssid_match_result res;
411
412         ie = mgmt->u.probe_req.variable;
413         if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
414                 return;
415         ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
416
417         for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
418                 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
419                                             mgmt->sa, mgmt->da, mgmt->bssid,
420                                             ie, ie_len, ssi_signal) > 0)
421                         return;
422
423         if (!hapd->iconf->send_probe_response)
424                 return;
425
426         if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
427                 wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
428                            MAC2STR(mgmt->sa));
429                 return;
430         }
431
432         if ((!elems.ssid || !elems.supp_rates)) {
433                 wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
434                            "without SSID or supported rates element",
435                            MAC2STR(mgmt->sa));
436                 return;
437         }
438
439 #ifdef CONFIG_P2P
440         if (hapd->p2p && elems.wps_ie) {
441                 struct wpabuf *wps;
442                 wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
443                 if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
444                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
445                                    "due to mismatch with Requested Device "
446                                    "Type");
447                         wpabuf_free(wps);
448                         return;
449                 }
450                 wpabuf_free(wps);
451         }
452
453         if (hapd->p2p && elems.p2p) {
454                 struct wpabuf *p2p;
455                 p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
456                 if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
457                         wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
458                                    "due to mismatch with Device ID");
459                         wpabuf_free(p2p);
460                         return;
461                 }
462                 wpabuf_free(p2p);
463         }
464 #endif /* CONFIG_P2P */
465
466         if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
467             elems.ssid_list_len == 0) {
468                 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
469                            "broadcast SSID ignored", MAC2STR(mgmt->sa));
470                 return;
471         }
472
473         sta = ap_get_sta(hapd, mgmt->sa);
474
475 #ifdef CONFIG_P2P
476         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
477             elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
478             os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
479                       P2P_WILDCARD_SSID_LEN) == 0) {
480                 /* Process P2P Wildcard SSID like Wildcard SSID */
481                 elems.ssid_len = 0;
482         }
483 #endif /* CONFIG_P2P */
484
485         res = ssid_match(hapd, elems.ssid, elems.ssid_len,
486                          elems.ssid_list, elems.ssid_list_len);
487         if (res != NO_SSID_MATCH) {
488                 if (sta)
489                         sta->ssid_probe = &hapd->conf->ssid;
490         } else {
491                 if (!(mgmt->da[0] & 0x01)) {
492                         char ssid_txt[33];
493                         ieee802_11_print_ssid(ssid_txt, elems.ssid,
494                                               elems.ssid_len);
495                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
496                                    " for foreign SSID '%s' (DA " MACSTR ")%s",
497                                    MAC2STR(mgmt->sa), ssid_txt,
498                                    MAC2STR(mgmt->da),
499                                    elems.ssid_list ? " (SSID list)" : "");
500                 }
501                 return;
502         }
503
504 #ifdef CONFIG_INTERWORKING
505         if (elems.interworking && elems.interworking_len >= 1) {
506                 u8 ant = elems.interworking[0] & 0x0f;
507                 if (ant != INTERWORKING_ANT_WILDCARD &&
508                     ant != hapd->conf->access_network_type) {
509                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
510                                    " for mismatching ANT %u ignored",
511                                    MAC2STR(mgmt->sa), ant);
512                         return;
513                 }
514         }
515
516         if (elems.interworking &&
517             (elems.interworking_len == 7 || elems.interworking_len == 9)) {
518                 const u8 *hessid;
519                 if (elems.interworking_len == 7)
520                         hessid = elems.interworking + 1;
521                 else
522                         hessid = elems.interworking + 1 + 2;
523                 if (!is_broadcast_ether_addr(hessid) &&
524                     os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
525                         wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
526                                    " for mismatching HESSID " MACSTR
527                                    " ignored",
528                                    MAC2STR(mgmt->sa), MAC2STR(hessid));
529                         return;
530                 }
531         }
532 #endif /* CONFIG_INTERWORKING */
533
534 #ifdef CONFIG_P2P
535         if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
536             supp_rates_11b_only(&elems)) {
537                 /* Indicates support for 11b rates only */
538                 wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
539                            MACSTR " with only 802.11b rates",
540                            MAC2STR(mgmt->sa));
541                 return;
542         }
543 #endif /* CONFIG_P2P */
544
545         /* TODO: verify that supp_rates contains at least one matching rate
546          * with AP configuration */
547
548 #ifdef CONFIG_TESTING_OPTIONS
549         if (hapd->iconf->ignore_probe_probability > 0.0d &&
550             drand48() < hapd->iconf->ignore_probe_probability) {
551                 wpa_printf(MSG_INFO,
552                            "TESTING: ignoring probe request from " MACSTR,
553                            MAC2STR(mgmt->sa));
554                 return;
555         }
556 #endif /* CONFIG_TESTING_OPTIONS */
557
558         resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
559                                       &resp_len);
560         if (resp == NULL)
561                 return;
562
563         /*
564          * If this is a broadcast probe request, apply no ack policy to avoid
565          * excessive retries.
566          */
567         noack = !!(res == WILDCARD_SSID_MATCH &&
568                    is_broadcast_ether_addr(mgmt->da));
569
570         if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
571                 wpa_printf(MSG_INFO, "handle_probe_req: send failed");
572
573         os_free(resp);
574
575         wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
576                    "SSID", MAC2STR(mgmt->sa),
577                    elems.ssid_len == 0 ? "broadcast" : "our");
578 }
579
580
581 static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
582                                         size_t *resp_len)
583 {
584         /* check probe response offloading caps and print warnings */
585         if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
586                 return NULL;
587
588 #ifdef CONFIG_WPS
589         if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
590             (!(hapd->iface->probe_resp_offloads &
591                (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
592                 WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
593                 wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
594                            "Probe Response while not supporting this");
595 #endif /* CONFIG_WPS */
596
597 #ifdef CONFIG_P2P
598         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
599             !(hapd->iface->probe_resp_offloads &
600               WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
601                 wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
602                            "Probe Response while not supporting this");
603 #endif  /* CONFIG_P2P */
604
605         if (hapd->conf->interworking &&
606             !(hapd->iface->probe_resp_offloads &
607               WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
608                 wpa_printf(MSG_WARNING, "Device is trying to offload "
609                            "Interworking Probe Response while not supporting "
610                            "this");
611
612         /* Generate a Probe Response template for the non-P2P case */
613         return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
614 }
615
616 #endif /* NEED_AP_MLME */
617
618
619 int ieee802_11_build_ap_params(struct hostapd_data *hapd,
620                                struct wpa_driver_ap_params *params)
621 {
622         struct ieee80211_mgmt *head = NULL;
623         u8 *tail = NULL;
624         size_t head_len = 0, tail_len = 0;
625         u8 *resp = NULL;
626         size_t resp_len = 0;
627 #ifdef NEED_AP_MLME
628         u16 capab_info;
629         u8 *pos, *tailpos, *old_pos;
630
631 #define BEACON_HEAD_BUF_SIZE 256
632 #define BEACON_TAIL_BUF_SIZE 512
633         head = os_zalloc(BEACON_HEAD_BUF_SIZE);
634         tail_len = BEACON_TAIL_BUF_SIZE;
635 #ifdef CONFIG_WPS
636         if (hapd->conf->wps_state && hapd->wps_beacon_ie)
637                 tail_len += wpabuf_len(hapd->wps_beacon_ie);
638 #endif /* CONFIG_WPS */
639 #ifdef CONFIG_P2P
640         if (hapd->p2p_beacon_ie)
641                 tail_len += wpabuf_len(hapd->p2p_beacon_ie);
642 #endif /* CONFIG_P2P */
643         if (hapd->conf->vendor_elements)
644                 tail_len += wpabuf_len(hapd->conf->vendor_elements);
645         tailpos = tail = os_malloc(tail_len);
646         if (head == NULL || tail == NULL) {
647                 wpa_printf(MSG_ERROR, "Failed to set beacon data");
648                 os_free(head);
649                 os_free(tail);
650                 return -1;
651         }
652
653         head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
654                                            WLAN_FC_STYPE_BEACON);
655         head->duration = host_to_le16(0);
656         os_memset(head->da, 0xff, ETH_ALEN);
657
658         os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
659         os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
660         head->u.beacon.beacon_int =
661                 host_to_le16(hapd->iconf->beacon_int);
662
663         /* hardware or low-level driver will setup seq_ctrl and timestamp */
664         capab_info = hostapd_own_capab_info(hapd, NULL, 0);
665         head->u.beacon.capab_info = host_to_le16(capab_info);
666         pos = &head->u.beacon.variable[0];
667
668         /* SSID */
669         *pos++ = WLAN_EID_SSID;
670         if (hapd->conf->ignore_broadcast_ssid == 2) {
671                 /* clear the data, but keep the correct length of the SSID */
672                 *pos++ = hapd->conf->ssid.ssid_len;
673                 os_memset(pos, 0, hapd->conf->ssid.ssid_len);
674                 pos += hapd->conf->ssid.ssid_len;
675         } else if (hapd->conf->ignore_broadcast_ssid) {
676                 *pos++ = 0; /* empty SSID */
677         } else {
678                 *pos++ = hapd->conf->ssid.ssid_len;
679                 os_memcpy(pos, hapd->conf->ssid.ssid,
680                           hapd->conf->ssid.ssid_len);
681                 pos += hapd->conf->ssid.ssid_len;
682         }
683
684         /* Supported rates */
685         pos = hostapd_eid_supp_rates(hapd, pos);
686
687         /* DS Params */
688         pos = hostapd_eid_ds_params(hapd, pos);
689
690         head_len = pos - (u8 *) head;
691
692         tailpos = hostapd_eid_country(hapd, tailpos,
693                                       tail + BEACON_TAIL_BUF_SIZE - tailpos);
694
695         /* ERP Information element */
696         tailpos = hostapd_eid_erp_info(hapd, tailpos);
697
698         /* Extended supported rates */
699         tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
700
701         /* RSN, MDIE, WPA */
702         tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
703                                   tailpos);
704
705         tailpos = hostapd_eid_bss_load(hapd, tailpos,
706                                        tail + BEACON_TAIL_BUF_SIZE - tailpos);
707
708 #ifdef CONFIG_IEEE80211N
709         tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
710         tailpos = hostapd_eid_ht_operation(hapd, tailpos);
711 #endif /* CONFIG_IEEE80211N */
712
713         tailpos = hostapd_eid_ext_capab(hapd, tailpos);
714
715         /*
716          * TODO: Time Advertisement element should only be included in some
717          * DTIM Beacon frames.
718          */
719         tailpos = hostapd_eid_time_adv(hapd, tailpos);
720
721         tailpos = hostapd_eid_interworking(hapd, tailpos);
722         tailpos = hostapd_eid_adv_proto(hapd, tailpos);
723         tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
724         old_pos = tailpos;
725         tailpos = hostapd_eid_csa(hapd, tailpos);
726         hapd->iface->cs_c_off_beacon = (old_pos != tailpos) ?
727                 tailpos - tail - 1 : 0;
728
729 #ifdef CONFIG_IEEE80211AC
730         tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
731         tailpos = hostapd_eid_vht_operation(hapd, tailpos);
732 #endif /* CONFIG_IEEE80211AC */
733
734         /* Wi-Fi Alliance WMM */
735         tailpos = hostapd_eid_wmm(hapd, tailpos);
736
737 #ifdef CONFIG_WPS
738         if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
739                 os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
740                           wpabuf_len(hapd->wps_beacon_ie));
741                 tailpos += wpabuf_len(hapd->wps_beacon_ie);
742         }
743 #endif /* CONFIG_WPS */
744
745 #ifdef CONFIG_P2P
746         if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
747                 os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
748                           wpabuf_len(hapd->p2p_beacon_ie));
749                 tailpos += wpabuf_len(hapd->p2p_beacon_ie);
750         }
751 #endif /* CONFIG_P2P */
752 #ifdef CONFIG_P2P_MANAGER
753         if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
754             P2P_MANAGE)
755                 tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
756 #endif /* CONFIG_P2P_MANAGER */
757
758 #ifdef CONFIG_HS20
759         tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
760 #endif /* CONFIG_HS20 */
761
762         if (hapd->conf->vendor_elements) {
763                 os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
764                           wpabuf_len(hapd->conf->vendor_elements));
765                 tailpos += wpabuf_len(hapd->conf->vendor_elements);
766         }
767
768         tail_len = tailpos > tail ? tailpos - tail : 0;
769
770         resp = hostapd_probe_resp_offloads(hapd, &resp_len);
771 #endif /* NEED_AP_MLME */
772
773         os_memset(params, 0, sizeof(*params));
774         params->head = (u8 *) head;
775         params->head_len = head_len;
776         params->tail = tail;
777         params->tail_len = tail_len;
778         params->proberesp = resp;
779         params->proberesp_len = resp_len;
780         params->dtim_period = hapd->conf->dtim_period;
781         params->beacon_int = hapd->iconf->beacon_int;
782         params->basic_rates = hapd->iface->basic_rates;
783         params->ssid = hapd->conf->ssid.ssid;
784         params->ssid_len = hapd->conf->ssid.ssid_len;
785         params->pairwise_ciphers = hapd->conf->rsn_pairwise ?
786                 hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise;
787         params->group_cipher = hapd->conf->wpa_group;
788         params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
789         params->auth_algs = hapd->conf->auth_algs;
790         params->wpa_version = hapd->conf->wpa;
791         params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
792                 (hapd->conf->ieee802_1x &&
793                  (hapd->conf->default_wep_key_len ||
794                   hapd->conf->individual_wep_key_len));
795         switch (hapd->conf->ignore_broadcast_ssid) {
796         case 0:
797                 params->hide_ssid = NO_SSID_HIDING;
798                 break;
799         case 1:
800                 params->hide_ssid = HIDDEN_SSID_ZERO_LEN;
801                 break;
802         case 2:
803                 params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
804                 break;
805         }
806         params->isolate = hapd->conf->isolate;
807 #ifdef NEED_AP_MLME
808         params->cts_protect = !!(ieee802_11_erp_info(hapd) &
809                                 ERP_INFO_USE_PROTECTION);
810         params->preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
811                 hapd->iconf->preamble == SHORT_PREAMBLE;
812         if (hapd->iface->current_mode &&
813             hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
814                 params->short_slot_time =
815                         hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
816         else
817                 params->short_slot_time = -1;
818         if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
819                 params->ht_opmode = -1;
820         else
821                 params->ht_opmode = hapd->iface->ht_op_mode;
822 #endif /* NEED_AP_MLME */
823         params->interworking = hapd->conf->interworking;
824         if (hapd->conf->interworking &&
825             !is_zero_ether_addr(hapd->conf->hessid))
826                 params->hessid = hapd->conf->hessid;
827         params->access_network_type = hapd->conf->access_network_type;
828         params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
829 #ifdef CONFIG_HS20
830         params->disable_dgaf = hapd->conf->disable_dgaf;
831 #endif /* CONFIG_HS20 */
832         return 0;
833 }
834
835
836 void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
837 {
838         os_free(params->tail);
839         params->tail = NULL;
840         os_free(params->head);
841         params->head = NULL;
842         os_free(params->proberesp);
843         params->proberesp = NULL;
844 }
845
846
847 void ieee802_11_set_beacon(struct hostapd_data *hapd)
848 {
849         struct wpa_driver_ap_params params;
850         struct wpabuf *beacon, *proberesp, *assocresp;
851
852         if (hapd->iface->csa_in_progress) {
853                 wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
854                 return;
855         }
856
857         hapd->beacon_set_done = 1;
858
859         if (ieee802_11_build_ap_params(hapd, &params) < 0)
860                 return;
861
862         if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
863             0)
864                 goto fail;
865
866         params.beacon_ies = beacon;
867         params.proberesp_ies = proberesp;
868         params.assocresp_ies = assocresp;
869
870         if (hostapd_drv_set_ap(hapd, &params))
871                 wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
872         hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
873 fail:
874         ieee802_11_free_ap_params(&params);
875 }
876
877
878 void ieee802_11_set_beacons(struct hostapd_iface *iface)
879 {
880         size_t i;
881         for (i = 0; i < iface->num_bss; i++) {
882                 if (iface->bss[i]->started)
883                         ieee802_11_set_beacon(iface->bss[i]);
884         }
885 }
886
887
888 /* only update beacons if started */
889 void ieee802_11_update_beacons(struct hostapd_iface *iface)
890 {
891         size_t i;
892         for (i = 0; i < iface->num_bss; i++)
893                 if (iface->bss[i]->beacon_set_done && iface->bss[i]->started)
894                         ieee802_11_set_beacon(iface->bss[i]);
895 }
896
897 #endif /* CONFIG_NATIVE_WINDOWS */