beacon.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
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-2009, 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 37 38static u8 ieee802_11_erp_info(struct hostapd_data *hapd) 39{ 40 u8 erp = 0; 41 42 if (hapd->iface->current_mode == NULL || 43 hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) 44 return 0; 45 46 switch (hapd->iconf->cts_protection_type) { 47 case CTS_PROTECTION_FORCE_ENABLED: 48 erp |= ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION; 49 break; 50 case CTS_PROTECTION_FORCE_DISABLED: 51 erp = 0; 52 break; 53 case CTS_PROTECTION_AUTOMATIC: 54 if (hapd->iface->olbc) 55 erp |= ERP_INFO_USE_PROTECTION; 56 /* continue */ 57 case CTS_PROTECTION_AUTOMATIC_NO_OLBC: 58 if (hapd->iface->num_sta_non_erp > 0) { 59 erp |= ERP_INFO_NON_ERP_PRESENT | 60 ERP_INFO_USE_PROTECTION; 61 } 62 break; 63 } 64 if (hapd->iface->num_sta_no_short_preamble > 0 || 65 hapd->iconf->preamble == LONG_PREAMBLE) 66 erp |= ERP_INFO_BARKER_PREAMBLE_MODE; 67 68 return erp; 69} 70 71 72static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid) 73{ 74 *eid++ = WLAN_EID_DS_PARAMS; 75 *eid++ = 1; 76 *eid++ = hapd->iconf->channel; 77 return eid; 78} 79 80 81static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) 82{ 83 if (hapd->iface->current_mode == NULL || 84 hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) 85 return eid; 86 87 /* Set NonERP_present and use_protection bits if there 88 * are any associated NonERP stations. */ 89 /* TODO: use_protection bit can be set to zero even if 90 * there are NonERP stations present. This optimization 91 * might be useful if NonERP stations are "quiet". 92 * See 802.11g/D6 E-1 for recommended practice. 93 * In addition, Non ERP present might be set, if AP detects Non ERP 94 * operation on other APs. */ 95 96 /* Add ERP Information element */ 97 *eid++ = WLAN_EID_ERP_INFO; 98 *eid++ = 1; 99 *eid++ = ieee802_11_erp_info(hapd); 100 101 return eid; 102} 103 104 105static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, 106 struct hostapd_channel_data *start, 107 struct hostapd_channel_data *prev) 108{ 109 if (end - pos < 3) 110 return pos; 111 112 /* first channel number */ 113 *pos++ = start->chan; 114 /* number of channels */ 115 *pos++ = (prev->chan - start->chan) / chan_spacing + 1; 116 /* maximum transmit power level */ 117 *pos++ = start->max_tx_power; 118 119 return pos; 120} 121 122 123static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, 124 int max_len) 125{ 126 u8 *pos = eid; 127 u8 *end = eid + max_len; 128 int i; 129 struct hostapd_hw_modes *mode; 130 struct hostapd_channel_data *start, *prev; 131 int chan_spacing = 1; 132 133 if (!hapd->iconf->ieee80211d || max_len < 6 || 134 hapd->iface->current_mode == NULL) 135 return eid; 136 137 *pos++ = WLAN_EID_COUNTRY; 138 pos++; /* length will be set later */ 139 os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ 140 pos += 3; 141 142 mode = hapd->iface->current_mode; 143 if (mode->mode == HOSTAPD_MODE_IEEE80211A) 144 chan_spacing = 4; 145 146 start = prev = NULL; 147 for (i = 0; i < mode->num_channels; i++) { 148 struct hostapd_channel_data *chan = &mode->channels[i]; 149 if (chan->flag & HOSTAPD_CHAN_DISABLED) 150 continue; 151 if (start && prev && 152 prev->chan + chan_spacing == chan->chan && 153 start->max_tx_power == chan->max_tx_power) { 154 prev = chan; 155 continue; /* can use same entry */ 156 } 157 158 if (start) { 159 pos = hostapd_eid_country_add(pos, end, chan_spacing, 160 start, prev); 161 start = NULL; 162 } 163 164 /* Start new group */ 165 start = prev = chan; 166 } 167 168 if (start) { 169 pos = hostapd_eid_country_add(pos, end, chan_spacing, 170 start, prev); 171 } 172 173 if ((pos - eid) & 1) { 174 if (end - pos < 1) 175 return eid; 176 *pos++ = 0; /* pad for 16-bit alignment */ 177 } 178 179 eid[1] = (pos - eid) - 2; 180 181 return pos; 182} 183 184 185static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len, 186 struct sta_info *sta) 187{ 188 const u8 *ie; 189 size_t ielen; 190 191 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); 192 if (ie == NULL || ielen > len) 193 return eid; 194 195 os_memcpy(eid, ie, ielen); 196 return eid + ielen; 197} 198 199 200void handle_probe_req(struct hostapd_data *hapd, 201 const struct ieee80211_mgmt *mgmt, size_t len) 202{ 203 struct ieee80211_mgmt *resp; 204 struct ieee802_11_elems elems; 205 char *ssid; 206 u8 *pos, *epos; 207 const u8 *ie; 208 size_t ssid_len, ie_len; 209 struct sta_info *sta = NULL; 210 size_t buflen; 211 size_t i; 212 213 ie = mgmt->u.probe_req.variable; 214 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) 215 return; 216 ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); 217 218 for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) 219 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, 220 mgmt->sa, ie, ie_len) > 0) 221 return; 222 223 if (!hapd->iconf->send_probe_response) 224 return; 225 226 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { 227 wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, 228 MAC2STR(mgmt->sa)); 229 return; 230 } 231 232 ssid = NULL; 233 ssid_len = 0; 234 235 if ((!elems.ssid || !elems.supp_rates)) { 236 wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " 237 "without SSID or supported rates element", 238 MAC2STR(mgmt->sa)); 239 return; 240 } 241 242#ifdef CONFIG_P2P 243 if (hapd->p2p && elems.wps_ie) { 244 struct wpabuf *wps; 245 wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); 246 if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { 247 wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " 248 "due to mismatch with Requested Device " 249 "Type"); 250 wpabuf_free(wps); 251 return; 252 } 253 wpabuf_free(wps); 254 } 255#endif /* CONFIG_P2P */ 256 257 if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { 258 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " 259 "broadcast SSID ignored", MAC2STR(mgmt->sa)); 260 return; 261 } 262 263 sta = ap_get_sta(hapd, mgmt->sa); 264 265#ifdef CONFIG_P2P 266 if ((hapd->conf->p2p & P2P_GROUP_OWNER) && 267 elems.ssid_len == P2P_WILDCARD_SSID_LEN && 268 os_memcmp(elems.ssid, P2P_WILDCARD_SSID, 269 P2P_WILDCARD_SSID_LEN) == 0) { 270 /* Process P2P Wildcard SSID like Wildcard SSID */ 271 elems.ssid_len = 0; 272 } 273#endif /* CONFIG_P2P */ 274 275 if (elems.ssid_len == 0 || 276 (elems.ssid_len == hapd->conf->ssid.ssid_len && 277 os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == 278 0)) { 279 ssid = hapd->conf->ssid.ssid; 280 ssid_len = hapd->conf->ssid.ssid_len; 281 if (sta) 282 sta->ssid_probe = &hapd->conf->ssid; 283 } 284 285 if (!ssid) { 286 if (!(mgmt->da[0] & 0x01)) { 287 char ssid_txt[33]; 288 ieee802_11_print_ssid(ssid_txt, elems.ssid, 289 elems.ssid_len); 290 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR 291 " for foreign SSID '%s' (DA " MACSTR ")", 292 MAC2STR(mgmt->sa), ssid_txt, 293 MAC2STR(mgmt->da)); 294 } 295 return; 296 } 297 298 /* TODO: verify that supp_rates contains at least one matching rate 299 * with AP configuration */ 300#define MAX_PROBERESP_LEN 768 301 buflen = MAX_PROBERESP_LEN; 302#ifdef CONFIG_WPS 303 if (hapd->wps_probe_resp_ie) 304 buflen += wpabuf_len(hapd->wps_probe_resp_ie); 305#endif /* CONFIG_WPS */ 306#ifdef CONFIG_P2P 307 if (hapd->p2p_probe_resp_ie) 308 buflen += wpabuf_len(hapd->p2p_probe_resp_ie); 309#endif /* CONFIG_P2P */ 310 resp = os_zalloc(buflen); 311 if (resp == NULL) 312 return; 313 epos = ((u8 *) resp) + MAX_PROBERESP_LEN; 314 315 resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 316 WLAN_FC_STYPE_PROBE_RESP); 317 os_memcpy(resp->da, mgmt->sa, ETH_ALEN); 318 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); 319 320 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); 321 resp->u.probe_resp.beacon_int = 322 host_to_le16(hapd->iconf->beacon_int); 323 324 /* hardware or low-level driver will setup seq_ctrl and timestamp */ 325 resp->u.probe_resp.capab_info = 326 host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); 327 328 pos = resp->u.probe_resp.variable; 329 *pos++ = WLAN_EID_SSID; 330 *pos++ = ssid_len; 331 os_memcpy(pos, ssid, ssid_len); 332 pos += ssid_len; 333 334 /* Supported rates */ 335 pos = hostapd_eid_supp_rates(hapd, pos); 336 337 /* DS Params */ 338 pos = hostapd_eid_ds_params(hapd, pos); 339 340 pos = hostapd_eid_country(hapd, pos, epos - pos); 341 342 /* ERP Information element */ 343 pos = hostapd_eid_erp_info(hapd, pos); 344 345 /* Extended supported rates */ 346 pos = hostapd_eid_ext_supp_rates(hapd, pos); 347 348 /* RSN, MDIE, WPA */ 349 pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); 350 351#ifdef CONFIG_IEEE80211N 352 pos = hostapd_eid_ht_capabilities(hapd, pos); 353 pos = hostapd_eid_ht_operation(hapd, pos); 354#endif /* CONFIG_IEEE80211N */ 355 356 pos = hostapd_eid_ext_capab(hapd, pos); 357 358 /* Wi-Fi Alliance WMM */ 359 pos = hostapd_eid_wmm(hapd, pos); 360 361#ifdef CONFIG_WPS 362 if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { 363 os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), 364 wpabuf_len(hapd->wps_probe_resp_ie)); 365 pos += wpabuf_len(hapd->wps_probe_resp_ie); 366 } 367#endif /* CONFIG_WPS */ 368 369#ifdef CONFIG_P2P 370 if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p && 371 hapd->p2p_probe_resp_ie) { 372 os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), 373 wpabuf_len(hapd->p2p_probe_resp_ie)); 374 pos += wpabuf_len(hapd->p2p_probe_resp_ie); 375 } 376#endif /* CONFIG_P2P */ 377#ifdef CONFIG_P2P_MANAGER 378 if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == 379 P2P_MANAGE) 380 pos = hostapd_eid_p2p_manage(hapd, pos); 381#endif /* CONFIG_P2P_MANAGER */ 382 383 if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0) 384 perror("handle_probe_req: send"); 385 386 os_free(resp); 387 388 wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " 389 "SSID", MAC2STR(mgmt->sa), 390 elems.ssid_len == 0 ? "broadcast" : "our"); 391} 392 393 394void ieee802_11_set_beacon(struct hostapd_data *hapd) 395{ 396 struct ieee80211_mgmt *head; 397 u8 *pos, *tail, *tailpos; 398 u16 capab_info; 399 size_t head_len, tail_len; 400 401#ifdef CONFIG_P2P 402 if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED) 403 goto no_beacon; 404#endif /* CONFIG_P2P */ 405 406#define BEACON_HEAD_BUF_SIZE 256 407#define BEACON_TAIL_BUF_SIZE 512 408 head = os_zalloc(BEACON_HEAD_BUF_SIZE); 409 tail_len = BEACON_TAIL_BUF_SIZE; 410#ifdef CONFIG_WPS 411 if (hapd->conf->wps_state && hapd->wps_beacon_ie) 412 tail_len += wpabuf_len(hapd->wps_beacon_ie); 413#endif /* CONFIG_WPS */ 414#ifdef CONFIG_P2P 415 if (hapd->p2p_beacon_ie) 416 tail_len += wpabuf_len(hapd->p2p_beacon_ie); 417#endif /* CONFIG_P2P */ 418 tailpos = tail = os_malloc(tail_len); 419 if (head == NULL || tail == NULL) { 420 wpa_printf(MSG_ERROR, "Failed to set beacon data"); 421 os_free(head); 422 os_free(tail); 423 return; 424 } 425 426 head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 427 WLAN_FC_STYPE_BEACON); 428 head->duration = host_to_le16(0); 429 os_memset(head->da, 0xff, ETH_ALEN); 430 431 os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); 432 os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); 433 head->u.beacon.beacon_int = 434 host_to_le16(hapd->iconf->beacon_int); 435 436 /* hardware or low-level driver will setup seq_ctrl and timestamp */ 437 capab_info = hostapd_own_capab_info(hapd, NULL, 0); 438 head->u.beacon.capab_info = host_to_le16(capab_info); 439 pos = &head->u.beacon.variable[0]; 440 441 /* SSID */ 442 *pos++ = WLAN_EID_SSID; 443 if (hapd->conf->ignore_broadcast_ssid == 2) { 444 /* clear the data, but keep the correct length of the SSID */ 445 *pos++ = hapd->conf->ssid.ssid_len; 446 os_memset(pos, 0, hapd->conf->ssid.ssid_len); 447 pos += hapd->conf->ssid.ssid_len; 448 } else if (hapd->conf->ignore_broadcast_ssid) { 449 *pos++ = 0; /* empty SSID */ 450 } else { 451 *pos++ = hapd->conf->ssid.ssid_len; 452 os_memcpy(pos, hapd->conf->ssid.ssid, 453 hapd->conf->ssid.ssid_len); 454 pos += hapd->conf->ssid.ssid_len; 455 } 456 457 /* Supported rates */ 458 pos = hostapd_eid_supp_rates(hapd, pos); 459 460 /* DS Params */ 461 pos = hostapd_eid_ds_params(hapd, pos); 462 463 head_len = pos - (u8 *) head; 464 465 tailpos = hostapd_eid_country(hapd, tailpos, 466 tail + BEACON_TAIL_BUF_SIZE - tailpos); 467 468 /* ERP Information element */ 469 tailpos = hostapd_eid_erp_info(hapd, tailpos); 470 471 /* Extended supported rates */ 472 tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); 473 474 /* RSN, MDIE, WPA */ 475 tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - 476 tailpos, NULL); 477 478#ifdef CONFIG_IEEE80211N 479 tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); 480 tailpos = hostapd_eid_ht_operation(hapd, tailpos); 481#endif /* CONFIG_IEEE80211N */ 482 483 tailpos = hostapd_eid_ext_capab(hapd, tailpos); 484 485 /* Wi-Fi Alliance WMM */ 486 tailpos = hostapd_eid_wmm(hapd, tailpos); 487 488#ifdef CONFIG_WPS 489 if (hapd->conf->wps_state && hapd->wps_beacon_ie) { 490 os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), 491 wpabuf_len(hapd->wps_beacon_ie)); 492 tailpos += wpabuf_len(hapd->wps_beacon_ie); 493 } 494#endif /* CONFIG_WPS */ 495 496#ifdef CONFIG_P2P 497 if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { 498 os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), 499 wpabuf_len(hapd->p2p_beacon_ie)); 500 tailpos += wpabuf_len(hapd->p2p_beacon_ie); 501 } 502#endif /* CONFIG_P2P */ 503#ifdef CONFIG_P2P_MANAGER 504 if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == 505 P2P_MANAGE) 506 tailpos = hostapd_eid_p2p_manage(hapd, tailpos); 507#endif /* CONFIG_P2P_MANAGER */ 508 509 tail_len = tailpos > tail ? tailpos - tail : 0; 510 511 if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len, 512 tail, tail_len, hapd->conf->dtim_period, 513 hapd->iconf->beacon_int)) 514 wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM " 515 "period"); 516 517 os_free(tail); 518 os_free(head); 519 520#ifdef CONFIG_P2P 521no_beacon: 522#endif /* CONFIG_P2P */ 523 hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) & 524 ERP_INFO_USE_PROTECTION)); 525} 526 527 528void ieee802_11_set_beacons(struct hostapd_iface *iface) 529{ 530 size_t i; 531 for (i = 0; i < iface->num_bss; i++) 532 ieee802_11_set_beacon(iface->bss[i]); 533} 534 535#endif /* CONFIG_NATIVE_WINDOWS */ 536