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 (at) 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 38 static 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 72 static 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 81 static 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 105 static 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 123 static 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 185 static 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 200 void 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 #ifndef ANDROID_BRCM_P2P_PATCH 219 for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) 220 if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, 221 mgmt->sa, ie, ie_len) > 0) 222 return; 223 #endif 224 if (!hapd->iconf->send_probe_response) 225 return; 226 227 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { 228 wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, 229 MAC2STR(mgmt->sa)); 230 return; 231 } 232 233 ssid = NULL; 234 ssid_len = 0; 235 236 if ((!elems.ssid || !elems.supp_rates)) { 237 wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " 238 "without SSID or supported rates element", 239 MAC2STR(mgmt->sa)); 240 return; 241 } 242 243 #ifdef CONFIG_P2P 244 if (hapd->p2p && elems.wps_ie) { 245 struct wpabuf *wps; 246 wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); 247 if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { 248 wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " 249 "due to mismatch with Requested Device " 250 "Type"); 251 wpabuf_free(wps); 252 return; 253 } 254 wpabuf_free(wps); 255 } 256 #endif /* CONFIG_P2P */ 257 258 if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { 259 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " 260 "broadcast SSID ignored", MAC2STR(mgmt->sa)); 261 return; 262 } 263 264 sta = ap_get_sta(hapd, mgmt->sa); 265 266 #ifdef CONFIG_P2P 267 if ((hapd->conf->p2p & P2P_GROUP_OWNER) && 268 elems.ssid_len == P2P_WILDCARD_SSID_LEN && 269 os_memcmp(elems.ssid, P2P_WILDCARD_SSID, 270 P2P_WILDCARD_SSID_LEN) == 0) { 271 /* Process P2P Wildcard SSID like Wildcard SSID */ 272 elems.ssid_len = 0; 273 } 274 #endif /* CONFIG_P2P */ 275 276 if (elems.ssid_len == 0 || 277 (elems.ssid_len == hapd->conf->ssid.ssid_len && 278 os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == 279 0)) { 280 ssid = hapd->conf->ssid.ssid; 281 ssid_len = hapd->conf->ssid.ssid_len; 282 if (sta) 283 sta->ssid_probe = &hapd->conf->ssid; 284 } 285 286 if (!ssid) { 287 if (!(mgmt->da[0] & 0x01)) { 288 char ssid_txt[33]; 289 ieee802_11_print_ssid(ssid_txt, elems.ssid, 290 elems.ssid_len); 291 wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR 292 " for foreign SSID '%s' (DA " MACSTR ")", 293 MAC2STR(mgmt->sa), ssid_txt, 294 MAC2STR(mgmt->da)); 295 } 296 return; 297 } 298 299 /* TODO: verify that supp_rates contains at least one matching rate 300 * with AP configuration */ 301 #define MAX_PROBERESP_LEN 768 302 buflen = MAX_PROBERESP_LEN; 303 #ifdef CONFIG_WPS 304 if (hapd->wps_probe_resp_ie) 305 buflen += wpabuf_len(hapd->wps_probe_resp_ie); 306 #endif /* CONFIG_WPS */ 307 #ifdef CONFIG_P2P 308 if (hapd->p2p_probe_resp_ie) 309 buflen += wpabuf_len(hapd->p2p_probe_resp_ie); 310 #endif /* CONFIG_P2P */ 311 resp = os_zalloc(buflen); 312 if (resp == NULL) 313 return; 314 epos = ((u8 *) resp) + MAX_PROBERESP_LEN; 315 316 resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 317 WLAN_FC_STYPE_PROBE_RESP); 318 os_memcpy(resp->da, mgmt->sa, ETH_ALEN); 319 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); 320 321 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); 322 resp->u.probe_resp.beacon_int = 323 host_to_le16(hapd->iconf->beacon_int); 324 325 /* hardware or low-level driver will setup seq_ctrl and timestamp */ 326 resp->u.probe_resp.capab_info = 327 host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); 328 329 pos = resp->u.probe_resp.variable; 330 *pos++ = WLAN_EID_SSID; 331 *pos++ = ssid_len; 332 os_memcpy(pos, ssid, ssid_len); 333 pos += ssid_len; 334 335 /* Supported rates */ 336 pos = hostapd_eid_supp_rates(hapd, pos); 337 338 /* DS Params */ 339 pos = hostapd_eid_ds_params(hapd, pos); 340 341 pos = hostapd_eid_country(hapd, pos, epos - pos); 342 343 /* ERP Information element */ 344 pos = hostapd_eid_erp_info(hapd, pos); 345 346 /* Extended supported rates */ 347 pos = hostapd_eid_ext_supp_rates(hapd, pos); 348 349 /* RSN, MDIE, WPA */ 350 pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); 351 352 #ifdef CONFIG_IEEE80211N 353 pos = hostapd_eid_ht_capabilities(hapd, pos); 354 pos = hostapd_eid_ht_operation(hapd, pos); 355 #endif /* CONFIG_IEEE80211N */ 356 357 pos = hostapd_eid_ext_capab(hapd, pos); 358 359 /* Wi-Fi Alliance WMM */ 360 pos = hostapd_eid_wmm(hapd, pos); 361 362 #ifdef CONFIG_WPS 363 if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { 364 os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), 365 wpabuf_len(hapd->wps_probe_resp_ie)); 366 pos += wpabuf_len(hapd->wps_probe_resp_ie); 367 } 368 #endif /* CONFIG_WPS */ 369 370 #ifdef CONFIG_P2P 371 if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p && 372 hapd->p2p_probe_resp_ie) { 373 os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), 374 wpabuf_len(hapd->p2p_probe_resp_ie)); 375 pos += wpabuf_len(hapd->p2p_probe_resp_ie); 376 } 377 #endif /* CONFIG_P2P */ 378 #ifdef CONFIG_P2P_MANAGER 379 if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == 380 P2P_MANAGE) 381 pos = hostapd_eid_p2p_manage(hapd, pos); 382 #endif /* CONFIG_P2P_MANAGER */ 383 384 if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0) 385 perror("handle_probe_req: send"); 386 387 os_free(resp); 388 389 wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " 390 "SSID", MAC2STR(mgmt->sa), 391 elems.ssid_len == 0 ? "broadcast" : "our"); 392 } 393 394 395 void ieee802_11_set_beacon(struct hostapd_data *hapd) 396 { 397 struct ieee80211_mgmt *head; 398 u8 *pos, *tail, *tailpos; 399 u16 capab_info; 400 size_t head_len, tail_len; 401 402 #ifdef CONFIG_P2P 403 if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED) 404 goto no_beacon; 405 #endif /* CONFIG_P2P */ 406 407 #define BEACON_HEAD_BUF_SIZE 256 408 #define BEACON_TAIL_BUF_SIZE 512 409 head = os_zalloc(BEACON_HEAD_BUF_SIZE); 410 tail_len = BEACON_TAIL_BUF_SIZE; 411 #ifdef CONFIG_WPS 412 if (hapd->conf->wps_state && hapd->wps_beacon_ie) 413 tail_len += wpabuf_len(hapd->wps_beacon_ie); 414 #endif /* CONFIG_WPS */ 415 #ifdef CONFIG_P2P 416 if (hapd->p2p_beacon_ie) 417 tail_len += wpabuf_len(hapd->p2p_beacon_ie); 418 #endif /* CONFIG_P2P */ 419 tailpos = tail = os_malloc(tail_len); 420 if (head == NULL || tail == NULL) { 421 wpa_printf(MSG_ERROR, "Failed to set beacon data"); 422 os_free(head); 423 os_free(tail); 424 return; 425 } 426 427 head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 428 WLAN_FC_STYPE_BEACON); 429 head->duration = host_to_le16(0); 430 os_memset(head->da, 0xff, ETH_ALEN); 431 432 os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); 433 os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); 434 head->u.beacon.beacon_int = 435 host_to_le16(hapd->iconf->beacon_int); 436 437 /* hardware or low-level driver will setup seq_ctrl and timestamp */ 438 capab_info = hostapd_own_capab_info(hapd, NULL, 0); 439 head->u.beacon.capab_info = host_to_le16(capab_info); 440 pos = &head->u.beacon.variable[0]; 441 442 /* SSID */ 443 *pos++ = WLAN_EID_SSID; 444 if (hapd->conf->ignore_broadcast_ssid == 2) { 445 /* clear the data, but keep the correct length of the SSID */ 446 *pos++ = hapd->conf->ssid.ssid_len; 447 os_memset(pos, 0, hapd->conf->ssid.ssid_len); 448 pos += hapd->conf->ssid.ssid_len; 449 } else if (hapd->conf->ignore_broadcast_ssid) { 450 *pos++ = 0; /* empty SSID */ 451 } else { 452 *pos++ = hapd->conf->ssid.ssid_len; 453 os_memcpy(pos, hapd->conf->ssid.ssid, 454 hapd->conf->ssid.ssid_len); 455 pos += hapd->conf->ssid.ssid_len; 456 } 457 458 /* Supported rates */ 459 pos = hostapd_eid_supp_rates(hapd, pos); 460 461 /* DS Params */ 462 pos = hostapd_eid_ds_params(hapd, pos); 463 464 head_len = pos - (u8 *) head; 465 466 tailpos = hostapd_eid_country(hapd, tailpos, 467 tail + BEACON_TAIL_BUF_SIZE - tailpos); 468 469 /* ERP Information element */ 470 tailpos = hostapd_eid_erp_info(hapd, tailpos); 471 472 /* Extended supported rates */ 473 tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); 474 475 /* RSN, MDIE, WPA */ 476 tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - 477 tailpos, NULL); 478 479 #ifdef CONFIG_IEEE80211N 480 tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); 481 tailpos = hostapd_eid_ht_operation(hapd, tailpos); 482 #endif /* CONFIG_IEEE80211N */ 483 484 tailpos = hostapd_eid_ext_capab(hapd, tailpos); 485 486 /* Wi-Fi Alliance WMM */ 487 tailpos = hostapd_eid_wmm(hapd, tailpos); 488 489 #ifdef CONFIG_WPS 490 if (hapd->conf->wps_state && hapd->wps_beacon_ie) { 491 os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), 492 wpabuf_len(hapd->wps_beacon_ie)); 493 tailpos += wpabuf_len(hapd->wps_beacon_ie); 494 } 495 #endif /* CONFIG_WPS */ 496 497 #ifdef CONFIG_P2P 498 if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { 499 os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), 500 wpabuf_len(hapd->p2p_beacon_ie)); 501 tailpos += wpabuf_len(hapd->p2p_beacon_ie); 502 } 503 #endif /* CONFIG_P2P */ 504 #ifdef CONFIG_P2P_MANAGER 505 if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == 506 P2P_MANAGE) 507 tailpos = hostapd_eid_p2p_manage(hapd, tailpos); 508 #endif /* CONFIG_P2P_MANAGER */ 509 510 tail_len = tailpos > tail ? tailpos - tail : 0; 511 512 if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len, 513 tail, tail_len, hapd->conf->dtim_period, 514 hapd->iconf->beacon_int)) 515 wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM " 516 "period"); 517 518 os_free(tail); 519 os_free(head); 520 521 #ifdef CONFIG_P2P 522 no_beacon: 523 #endif /* CONFIG_P2P */ 524 hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) & 525 ERP_INFO_USE_PROTECTION)); 526 } 527 528 529 void ieee802_11_set_beacons(struct hostapd_iface *iface) 530 { 531 size_t i; 532 for (i = 0; i < iface->num_bss; i++) 533 ieee802_11_set_beacon(iface->bss[i]); 534 } 535 536 #endif /* CONFIG_NATIVE_WINDOWS */ 537