1 /* 2 * hostapd - WNM 3 * Copyright (c) 2011-2014, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #include "utils/common.h" 12 #include "utils/eloop.h" 13 #include "common/ieee802_11_defs.h" 14 #include "common/wpa_ctrl.h" 15 #include "common/ocv.h" 16 #include "ap/hostapd.h" 17 #include "ap/sta_info.h" 18 #include "ap/ap_config.h" 19 #include "ap/ap_drv_ops.h" 20 #include "ap/wpa_auth.h" 21 #include "mbo_ap.h" 22 #include "wnm_ap.h" 23 24 #define MAX_TFS_IE_LEN 1024 25 26 27 /* get the TFS IE from driver */ 28 static int ieee80211_11_get_tfs_ie(struct hostapd_data *hapd, const u8 *addr, 29 u8 *buf, u16 *buf_len, enum wnm_oper oper) 30 { 31 wpa_printf(MSG_DEBUG, "%s: TFS get operation %d", __func__, oper); 32 33 return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len); 34 } 35 36 37 /* set the TFS IE to driver */ 38 static int ieee80211_11_set_tfs_ie(struct hostapd_data *hapd, const u8 *addr, 39 u8 *buf, u16 *buf_len, enum wnm_oper oper) 40 { 41 wpa_printf(MSG_DEBUG, "%s: TFS set operation %d", __func__, oper); 42 43 return hostapd_drv_wnm_oper(hapd, oper, addr, buf, buf_len); 44 } 45 46 47 /* MLME-SLEEPMODE.response */ 48 static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, 49 const u8 *addr, u8 dialog_token, 50 u8 action_type, u16 intval) 51 { 52 struct ieee80211_mgmt *mgmt; 53 int res; 54 size_t len; 55 size_t gtk_elem_len = 0; 56 size_t igtk_elem_len = 0; 57 size_t bigtk_elem_len = 0; 58 struct wnm_sleep_element wnmsleep_ie; 59 u8 *wnmtfs_ie, *oci_ie; 60 u8 wnmsleep_ie_len, oci_ie_len; 61 u16 wnmtfs_ie_len; 62 u8 *pos; 63 struct sta_info *sta; 64 enum wnm_oper tfs_oper = action_type == WNM_SLEEP_MODE_ENTER ? 65 WNM_SLEEP_TFS_RESP_IE_ADD : WNM_SLEEP_TFS_RESP_IE_NONE; 66 67 sta = ap_get_sta(hapd, addr); 68 if (sta == NULL) { 69 wpa_printf(MSG_DEBUG, "%s: station not found", __func__); 70 return -EINVAL; 71 } 72 73 /* WNM-Sleep Mode IE */ 74 os_memset(&wnmsleep_ie, 0, sizeof(struct wnm_sleep_element)); 75 wnmsleep_ie_len = sizeof(struct wnm_sleep_element); 76 wnmsleep_ie.eid = WLAN_EID_WNMSLEEP; 77 wnmsleep_ie.len = wnmsleep_ie_len - 2; 78 wnmsleep_ie.action_type = action_type; 79 wnmsleep_ie.status = WNM_STATUS_SLEEP_ACCEPT; 80 wnmsleep_ie.intval = host_to_le16(intval); 81 82 /* TFS IE(s) */ 83 wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN); 84 if (wnmtfs_ie == NULL) 85 return -1; 86 if (ieee80211_11_get_tfs_ie(hapd, addr, wnmtfs_ie, &wnmtfs_ie_len, 87 tfs_oper)) { 88 wnmtfs_ie_len = 0; 89 os_free(wnmtfs_ie); 90 wnmtfs_ie = NULL; 91 } 92 93 oci_ie = NULL; 94 oci_ie_len = 0; 95 #ifdef CONFIG_OCV 96 if (action_type == WNM_SLEEP_MODE_EXIT && 97 wpa_auth_uses_ocv(sta->wpa_sm)) { 98 struct wpa_channel_info ci; 99 100 if (hostapd_drv_channel_info(hapd, &ci) != 0) { 101 wpa_printf(MSG_WARNING, 102 "Failed to get channel info for OCI element in WNM-Sleep Mode frame"); 103 os_free(wnmtfs_ie); 104 return -1; 105 } 106 #ifdef CONFIG_TESTING_OPTIONS 107 if (hapd->conf->oci_freq_override_wnm_sleep) { 108 wpa_printf(MSG_INFO, 109 "TEST: Override OCI frequency %d -> %u MHz", 110 ci.frequency, 111 hapd->conf->oci_freq_override_wnm_sleep); 112 ci.frequency = hapd->conf->oci_freq_override_wnm_sleep; 113 } 114 #endif /* CONFIG_TESTING_OPTIONS */ 115 116 oci_ie_len = OCV_OCI_EXTENDED_LEN; 117 oci_ie = os_zalloc(oci_ie_len); 118 if (!oci_ie) { 119 wpa_printf(MSG_WARNING, 120 "Failed to allocate buffer for OCI element in WNM-Sleep Mode frame"); 121 os_free(wnmtfs_ie); 122 return -1; 123 } 124 125 if (ocv_insert_extended_oci(&ci, oci_ie) < 0) { 126 os_free(wnmtfs_ie); 127 os_free(oci_ie); 128 return -1; 129 } 130 } 131 #endif /* CONFIG_OCV */ 132 133 #define MAX_GTK_SUBELEM_LEN 45 134 #define MAX_IGTK_SUBELEM_LEN 26 135 #define MAX_BIGTK_SUBELEM_LEN 26 136 mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + 137 MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN + 138 MAX_BIGTK_SUBELEM_LEN + 139 oci_ie_len); 140 if (mgmt == NULL) { 141 wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " 142 "WNM-Sleep Response action frame"); 143 res = -1; 144 goto fail; 145 } 146 os_memcpy(mgmt->da, addr, ETH_ALEN); 147 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 148 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 149 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 150 WLAN_FC_STYPE_ACTION); 151 mgmt->u.action.category = WLAN_ACTION_WNM; 152 mgmt->u.action.u.wnm_sleep_resp.action = WNM_SLEEP_MODE_RESP; 153 mgmt->u.action.u.wnm_sleep_resp.dialogtoken = dialog_token; 154 pos = (u8 *)mgmt->u.action.u.wnm_sleep_resp.variable; 155 /* add key data if MFP is enabled */ 156 if (!wpa_auth_uses_mfp(sta->wpa_sm) || 157 hapd->conf->wnm_sleep_mode_no_keys || 158 action_type != WNM_SLEEP_MODE_EXIT) { 159 mgmt->u.action.u.wnm_sleep_resp.keydata_len = 0; 160 } else { 161 gtk_elem_len = wpa_wnmsleep_gtk_subelem(sta->wpa_sm, pos); 162 pos += gtk_elem_len; 163 wpa_printf(MSG_DEBUG, "Pass 4, gtk_len = %d", 164 (int) gtk_elem_len); 165 res = wpa_wnmsleep_igtk_subelem(sta->wpa_sm, pos); 166 if (res < 0) 167 goto fail; 168 igtk_elem_len = res; 169 pos += igtk_elem_len; 170 wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d", 171 (int) igtk_elem_len); 172 if (hapd->conf->beacon_prot && 173 (hapd->iface->drv_flags & 174 WPA_DRIVER_FLAGS_BEACON_PROTECTION)) { 175 res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos); 176 if (res < 0) 177 goto fail; 178 bigtk_elem_len = res; 179 pos += bigtk_elem_len; 180 wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d", 181 (int) bigtk_elem_len); 182 } 183 184 WPA_PUT_LE16((u8 *) 185 &mgmt->u.action.u.wnm_sleep_resp.keydata_len, 186 gtk_elem_len + igtk_elem_len + bigtk_elem_len); 187 } 188 os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len); 189 /* copy TFS IE here */ 190 pos += wnmsleep_ie_len; 191 if (wnmtfs_ie) { 192 os_memcpy(pos, wnmtfs_ie, wnmtfs_ie_len); 193 pos += wnmtfs_ie_len; 194 } 195 #ifdef CONFIG_OCV 196 /* copy OCV OCI here */ 197 if (oci_ie_len > 0) 198 os_memcpy(pos, oci_ie, oci_ie_len); 199 #endif /* CONFIG_OCV */ 200 201 len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len + 202 igtk_elem_len + bigtk_elem_len + 203 wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len; 204 205 /* In driver, response frame should be forced to sent when STA is in 206 * PS mode */ 207 res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, 208 mgmt->da, &mgmt->u.action.category, len); 209 210 if (!res) { 211 wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response " 212 "frame"); 213 214 /* when entering wnmsleep 215 * 1. pause the node in driver 216 * 2. mark the node so that AP won't update GTK/IGTK/BIGTK 217 * during WNM Sleep 218 */ 219 if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT && 220 wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) { 221 sta->flags |= WLAN_STA_WNM_SLEEP_MODE; 222 hostapd_drv_wnm_oper(hapd, WNM_SLEEP_ENTER_CONFIRM, 223 addr, NULL, NULL); 224 wpa_set_wnmsleep(sta->wpa_sm, 1); 225 } 226 /* when exiting wnmsleep 227 * 1. unmark the node 228 * 2. start GTK/IGTK/BIGTK update if MFP is not used 229 * 3. unpause the node in driver 230 */ 231 if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT || 232 wnmsleep_ie.status == 233 WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) && 234 wnmsleep_ie.action_type == WNM_SLEEP_MODE_EXIT) { 235 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; 236 wpa_set_wnmsleep(sta->wpa_sm, 0); 237 hostapd_drv_wnm_oper(hapd, WNM_SLEEP_EXIT_CONFIRM, 238 addr, NULL, NULL); 239 if (!wpa_auth_uses_mfp(sta->wpa_sm) || 240 hapd->conf->wnm_sleep_mode_no_keys) 241 wpa_wnmsleep_rekey_gtk(sta->wpa_sm); 242 } 243 } else 244 wpa_printf(MSG_DEBUG, "Fail to send WNM-Sleep Response frame"); 245 246 #undef MAX_GTK_SUBELEM_LEN 247 #undef MAX_IGTK_SUBELEM_LEN 248 #undef MAX_BIGTK_SUBELEM_LEN 249 fail: 250 os_free(wnmtfs_ie); 251 os_free(oci_ie); 252 os_free(mgmt); 253 return res; 254 } 255 256 257 static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd, 258 const u8 *addr, const u8 *frm, int len) 259 { 260 /* Dialog Token [1] | WNM-Sleep Mode IE | TFS Response IE */ 261 const u8 *pos = frm; 262 u8 dialog_token; 263 struct wnm_sleep_element *wnmsleep_ie = NULL; 264 /* multiple TFS Req IE (assuming consecutive) */ 265 u8 *tfsreq_ie_start = NULL; 266 u8 *tfsreq_ie_end = NULL; 267 u16 tfsreq_ie_len = 0; 268 #ifdef CONFIG_OCV 269 struct sta_info *sta; 270 const u8 *oci_ie = NULL; 271 u8 oci_ie_len = 0; 272 #endif /* CONFIG_OCV */ 273 274 if (!hapd->conf->wnm_sleep_mode) { 275 wpa_printf(MSG_DEBUG, "Ignore WNM-Sleep Mode Request from " 276 MACSTR " since WNM-Sleep Mode is disabled", 277 MAC2STR(addr)); 278 return; 279 } 280 281 if (len < 1) { 282 wpa_printf(MSG_DEBUG, 283 "WNM: Ignore too short WNM-Sleep Mode Request from " 284 MACSTR, MAC2STR(addr)); 285 return; 286 } 287 288 dialog_token = *pos++; 289 while (pos + 1 < frm + len) { 290 u8 ie_len = pos[1]; 291 if (pos + 2 + ie_len > frm + len) 292 break; 293 if (*pos == WLAN_EID_WNMSLEEP && 294 ie_len >= (int) sizeof(*wnmsleep_ie) - 2) 295 wnmsleep_ie = (struct wnm_sleep_element *) pos; 296 else if (*pos == WLAN_EID_TFS_REQ) { 297 if (!tfsreq_ie_start) 298 tfsreq_ie_start = (u8 *) pos; 299 tfsreq_ie_end = (u8 *) pos; 300 #ifdef CONFIG_OCV 301 } else if (*pos == WLAN_EID_EXTENSION && ie_len >= 1 && 302 pos[2] == WLAN_EID_EXT_OCV_OCI) { 303 oci_ie = pos + 3; 304 oci_ie_len = ie_len - 1; 305 #endif /* CONFIG_OCV */ 306 } else 307 wpa_printf(MSG_DEBUG, "WNM: EID %d not recognized", 308 *pos); 309 pos += ie_len + 2; 310 } 311 312 if (!wnmsleep_ie) { 313 wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found"); 314 return; 315 } 316 317 #ifdef CONFIG_OCV 318 sta = ap_get_sta(hapd, addr); 319 if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT && 320 sta && wpa_auth_uses_ocv(sta->wpa_sm)) { 321 struct wpa_channel_info ci; 322 323 if (hostapd_drv_channel_info(hapd, &ci) != 0) { 324 wpa_printf(MSG_WARNING, 325 "Failed to get channel info to validate received OCI in WNM-Sleep Mode frame"); 326 return; 327 } 328 329 if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, 330 channel_width_to_int(ci.chanwidth), 331 ci.seg1_idx) != OCI_SUCCESS) { 332 wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s", 333 ocv_errorstr); 334 return; 335 } 336 } 337 #endif /* CONFIG_OCV */ 338 339 if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_ENTER && 340 tfsreq_ie_start && tfsreq_ie_end && 341 tfsreq_ie_end - tfsreq_ie_start >= 0) { 342 tfsreq_ie_len = (tfsreq_ie_end + tfsreq_ie_end[1] + 2) - 343 tfsreq_ie_start; 344 wpa_printf(MSG_DEBUG, "TFS Req IE(s) found"); 345 /* pass the TFS Req IE(s) to driver for processing */ 346 if (ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start, 347 &tfsreq_ie_len, 348 WNM_SLEEP_TFS_REQ_IE_SET)) 349 wpa_printf(MSG_DEBUG, "Fail to set TFS Req IE"); 350 } 351 352 ieee802_11_send_wnmsleep_resp(hapd, addr, dialog_token, 353 wnmsleep_ie->action_type, 354 le_to_host16(wnmsleep_ie->intval)); 355 356 if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT) { 357 /* clear the tfs after sending the resp frame */ 358 ieee80211_11_set_tfs_ie(hapd, addr, tfsreq_ie_start, 359 &tfsreq_ie_len, WNM_SLEEP_TFS_IE_DEL); 360 } 361 } 362 363 364 static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd, 365 const u8 *addr, 366 u8 dialog_token) 367 { 368 struct ieee80211_mgmt *mgmt; 369 size_t len; 370 u8 *pos; 371 int res; 372 373 mgmt = os_zalloc(sizeof(*mgmt)); 374 if (mgmt == NULL) 375 return -1; 376 os_memcpy(mgmt->da, addr, ETH_ALEN); 377 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 378 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 379 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 380 WLAN_FC_STYPE_ACTION); 381 mgmt->u.action.category = WLAN_ACTION_WNM; 382 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 383 mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token; 384 mgmt->u.action.u.bss_tm_req.req_mode = 0; 385 mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0); 386 mgmt->u.action.u.bss_tm_req.validity_interval = 1; 387 pos = mgmt->u.action.u.bss_tm_req.variable; 388 389 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to " 390 MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u " 391 "validity_interval=%u", 392 MAC2STR(addr), dialog_token, 393 mgmt->u.action.u.bss_tm_req.req_mode, 394 le_to_host16(mgmt->u.action.u.bss_tm_req.disassoc_timer), 395 mgmt->u.action.u.bss_tm_req.validity_interval); 396 397 len = pos - &mgmt->u.action.category; 398 res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, 399 mgmt->da, &mgmt->u.action.category, len); 400 os_free(mgmt); 401 return res; 402 } 403 404 405 static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd, 406 const u8 *addr, const u8 *frm, 407 size_t len) 408 { 409 u8 dialog_token, reason; 410 const u8 *pos, *end; 411 int enabled = hapd->conf->bss_transition; 412 413 #ifdef CONFIG_MBO 414 if (hapd->conf->mbo_enabled) 415 enabled = 1; 416 #endif /* CONFIG_MBO */ 417 if (!enabled) { 418 wpa_printf(MSG_DEBUG, 419 "Ignore BSS Transition Management Query from " 420 MACSTR 421 " since BSS Transition Management is disabled", 422 MAC2STR(addr)); 423 return; 424 } 425 426 if (len < 2) { 427 wpa_printf(MSG_DEBUG, "WNM: Ignore too short BSS Transition Management Query from " 428 MACSTR, MAC2STR(addr)); 429 return; 430 } 431 432 pos = frm; 433 end = pos + len; 434 dialog_token = *pos++; 435 reason = *pos++; 436 437 wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Query from " 438 MACSTR " dialog_token=%u reason=%u", 439 MAC2STR(addr), dialog_token, reason); 440 441 wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", 442 pos, end - pos); 443 444 ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token); 445 } 446 447 448 void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx) 449 { 450 struct hostapd_data *hapd = eloop_ctx; 451 struct sta_info *sta = timeout_ctx; 452 453 if (sta->agreed_to_steer) { 454 wpa_printf(MSG_DEBUG, "%s: Reset steering flag for STA " MACSTR, 455 hapd->conf->iface, MAC2STR(sta->addr)); 456 sta->agreed_to_steer = 0; 457 } 458 } 459 460 461 static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, 462 const u8 *addr, const u8 *frm, 463 size_t len) 464 { 465 u8 dialog_token, status_code, bss_termination_delay; 466 const u8 *pos, *end; 467 int enabled = hapd->conf->bss_transition; 468 struct sta_info *sta; 469 470 #ifdef CONFIG_MBO 471 if (hapd->conf->mbo_enabled) 472 enabled = 1; 473 #endif /* CONFIG_MBO */ 474 if (!enabled) { 475 wpa_printf(MSG_DEBUG, 476 "Ignore BSS Transition Management Response from " 477 MACSTR 478 " since BSS Transition Management is disabled", 479 MAC2STR(addr)); 480 return; 481 } 482 483 if (len < 3) { 484 wpa_printf(MSG_DEBUG, "WNM: Ignore too short BSS Transition Management Response from " 485 MACSTR, MAC2STR(addr)); 486 return; 487 } 488 489 pos = frm; 490 end = pos + len; 491 dialog_token = *pos++; 492 status_code = *pos++; 493 bss_termination_delay = *pos++; 494 495 wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Response from " 496 MACSTR " dialog_token=%u status_code=%u " 497 "bss_termination_delay=%u", MAC2STR(addr), dialog_token, 498 status_code, bss_termination_delay); 499 500 sta = ap_get_sta(hapd, addr); 501 if (!sta) { 502 wpa_printf(MSG_DEBUG, "Station " MACSTR 503 " not found for received BSS TM Response", 504 MAC2STR(addr)); 505 return; 506 } 507 508 if (status_code == WNM_BSS_TM_ACCEPT) { 509 if (end - pos < ETH_ALEN) { 510 wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field"); 511 return; 512 } 513 sta->agreed_to_steer = 1; 514 eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); 515 eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer, 516 hapd, sta); 517 wpa_printf(MSG_DEBUG, "WNM: Target BSSID: " MACSTR, 518 MAC2STR(pos)); 519 wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR 520 " status_code=%u bss_termination_delay=%u target_bssid=" 521 MACSTR, 522 MAC2STR(addr), status_code, bss_termination_delay, 523 MAC2STR(pos)); 524 pos += ETH_ALEN; 525 } else { 526 sta->agreed_to_steer = 0; 527 wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR 528 " status_code=%u bss_termination_delay=%u", 529 MAC2STR(addr), status_code, bss_termination_delay); 530 } 531 532 wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries", 533 pos, end - pos); 534 } 535 536 537 static void wnm_beacon_protection_failure(struct hostapd_data *hapd, 538 const u8 *addr) 539 { 540 struct sta_info *sta; 541 542 if (!hapd->conf->beacon_prot || 543 !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION)) 544 return; 545 546 sta = ap_get_sta(hapd, addr); 547 if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) { 548 wpa_printf(MSG_DEBUG, "Station " MACSTR 549 " not found for received WNM-Notification Request", 550 MAC2STR(addr)); 551 return; 552 } 553 554 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 555 HOSTAPD_LEVEL_INFO, 556 "Beacon protection failure reported"); 557 wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter=" 558 MACSTR, MAC2STR(addr)); 559 } 560 561 562 static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd, 563 const u8 *addr, const u8 *buf, 564 size_t len) 565 { 566 u8 dialog_token, type; 567 568 if (len < 2) 569 return; 570 dialog_token = *buf++; 571 type = *buf++; 572 len -= 2; 573 574 wpa_printf(MSG_DEBUG, 575 "WNM: Received WNM Notification Request frame from " 576 MACSTR " (dialog_token=%u type=%u)", 577 MAC2STR(addr), dialog_token, type); 578 wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements", 579 buf, len); 580 switch (type) { 581 case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE: 582 wnm_beacon_protection_failure(hapd, addr); 583 break; 584 case WNM_NOTIF_TYPE_VENDOR_SPECIFIC: 585 mbo_ap_wnm_notification_req(hapd, addr, buf, len); 586 break; 587 } 588 } 589 590 591 static void ieee802_11_rx_wnm_coloc_intf_report(struct hostapd_data *hapd, 592 const u8 *addr, const u8 *buf, 593 size_t len) 594 { 595 u8 dialog_token; 596 char *hex; 597 size_t hex_len; 598 599 if (!hapd->conf->coloc_intf_reporting) { 600 wpa_printf(MSG_DEBUG, 601 "WNM: Ignore unexpected Collocated Interference Report from " 602 MACSTR, MAC2STR(addr)); 603 return; 604 } 605 606 if (len < 1) { 607 wpa_printf(MSG_DEBUG, 608 "WNM: Ignore too short Collocated Interference Report from " 609 MACSTR, MAC2STR(addr)); 610 return; 611 } 612 dialog_token = *buf++; 613 len--; 614 615 wpa_printf(MSG_DEBUG, 616 "WNM: Received Collocated Interference Report frame from " 617 MACSTR " (dialog_token=%u)", 618 MAC2STR(addr), dialog_token); 619 wpa_hexdump(MSG_MSGDUMP, "WNM: Collocated Interference Report Elements", 620 buf, len); 621 622 hex_len = 2 * len + 1; 623 hex = os_malloc(hex_len); 624 if (!hex) 625 return; 626 wpa_snprintf_hex(hex, hex_len, buf, len); 627 wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, COLOC_INTF_REPORT MACSTR " %d %s", 628 MAC2STR(addr), dialog_token, hex); 629 os_free(hex); 630 } 631 632 633 int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd, 634 const struct ieee80211_mgmt *mgmt, size_t len) 635 { 636 u8 action; 637 const u8 *payload; 638 size_t plen; 639 640 if (len < IEEE80211_HDRLEN + 2) 641 return -1; 642 643 payload = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 1; 644 action = *payload++; 645 plen = len - IEEE80211_HDRLEN - 2; 646 647 switch (action) { 648 case WNM_BSS_TRANS_MGMT_QUERY: 649 ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload, 650 plen); 651 return 0; 652 case WNM_BSS_TRANS_MGMT_RESP: 653 ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload, 654 plen); 655 return 0; 656 case WNM_SLEEP_MODE_REQ: 657 ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen); 658 return 0; 659 case WNM_NOTIFICATION_REQ: 660 ieee802_11_rx_wnm_notification_req(hapd, mgmt->sa, payload, 661 plen); 662 return 0; 663 case WNM_COLLOCATED_INTERFERENCE_REPORT: 664 ieee802_11_rx_wnm_coloc_intf_report(hapd, mgmt->sa, payload, 665 plen); 666 return 0; 667 } 668 669 wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR, 670 action, MAC2STR(mgmt->sa)); 671 return -1; 672 } 673 674 675 int wnm_send_disassoc_imminent(struct hostapd_data *hapd, 676 struct sta_info *sta, int disassoc_timer) 677 { 678 u8 buf[1000], *pos; 679 struct ieee80211_mgmt *mgmt; 680 681 os_memset(buf, 0, sizeof(buf)); 682 mgmt = (struct ieee80211_mgmt *) buf; 683 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 684 WLAN_FC_STYPE_ACTION); 685 os_memcpy(mgmt->da, sta->addr, ETH_ALEN); 686 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 687 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 688 mgmt->u.action.category = WLAN_ACTION_WNM; 689 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 690 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 691 mgmt->u.action.u.bss_tm_req.req_mode = 692 WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 693 mgmt->u.action.u.bss_tm_req.disassoc_timer = 694 host_to_le16(disassoc_timer); 695 mgmt->u.action.u.bss_tm_req.validity_interval = 0; 696 697 pos = mgmt->u.action.u.bss_tm_req.variable; 698 699 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to " 700 MACSTR, disassoc_timer, MAC2STR(sta->addr)); 701 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { 702 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " 703 "Management Request frame"); 704 return -1; 705 } 706 707 return 0; 708 } 709 710 711 static void set_disassoc_timer(struct hostapd_data *hapd, struct sta_info *sta, 712 int disassoc_timer) 713 { 714 int timeout, beacon_int; 715 716 /* 717 * Prevent STA from reconnecting using cached PMKSA to force 718 * full authentication with the authentication server (which may 719 * decide to reject the connection), 720 */ 721 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr); 722 723 beacon_int = hapd->iconf->beacon_int; 724 if (beacon_int < 1) 725 beacon_int = 100; /* best guess */ 726 /* Calculate timeout in ms based on beacon_int in TU */ 727 timeout = disassoc_timer * beacon_int * 128 / 125; 728 wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR 729 " set to %d ms", MAC2STR(sta->addr), timeout); 730 731 sta->timeout_next = STA_DISASSOC_FROM_CLI; 732 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 733 eloop_register_timeout(timeout / 1000, 734 timeout % 1000 * 1000, 735 ap_handle_timer, hapd, sta); 736 } 737 738 739 int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd, 740 struct sta_info *sta, const char *url, 741 int disassoc_timer) 742 { 743 u8 buf[1000], *pos; 744 struct ieee80211_mgmt *mgmt; 745 size_t url_len; 746 747 os_memset(buf, 0, sizeof(buf)); 748 mgmt = (struct ieee80211_mgmt *) buf; 749 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 750 WLAN_FC_STYPE_ACTION); 751 os_memcpy(mgmt->da, sta->addr, ETH_ALEN); 752 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 753 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 754 mgmt->u.action.category = WLAN_ACTION_WNM; 755 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 756 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 757 mgmt->u.action.u.bss_tm_req.req_mode = 758 WNM_BSS_TM_REQ_DISASSOC_IMMINENT | 759 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 760 mgmt->u.action.u.bss_tm_req.disassoc_timer = 761 host_to_le16(disassoc_timer); 762 mgmt->u.action.u.bss_tm_req.validity_interval = 0x01; 763 764 pos = mgmt->u.action.u.bss_tm_req.variable; 765 766 /* Session Information URL */ 767 url_len = os_strlen(url); 768 if (url_len > 255) 769 return -1; 770 *pos++ = url_len; 771 os_memcpy(pos, url, url_len); 772 pos += url_len; 773 774 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { 775 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " 776 "Management Request frame"); 777 return -1; 778 } 779 780 if (disassoc_timer) { 781 /* send disassociation frame after time-out */ 782 set_disassoc_timer(hapd, sta, disassoc_timer); 783 } 784 785 return 0; 786 } 787 788 789 int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta, 790 u8 req_mode, int disassoc_timer, u8 valid_int, 791 const u8 *bss_term_dur, const char *url, 792 const u8 *nei_rep, size_t nei_rep_len, 793 const u8 *mbo_attrs, size_t mbo_len) 794 { 795 u8 *buf, *pos; 796 struct ieee80211_mgmt *mgmt; 797 size_t url_len; 798 799 wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to " 800 MACSTR " req_mode=0x%x disassoc_timer=%d valid_int=0x%x", 801 MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int); 802 buf = os_zalloc(1000 + nei_rep_len + mbo_len); 803 if (buf == NULL) 804 return -1; 805 mgmt = (struct ieee80211_mgmt *) buf; 806 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 807 WLAN_FC_STYPE_ACTION); 808 os_memcpy(mgmt->da, sta->addr, ETH_ALEN); 809 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 810 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 811 mgmt->u.action.category = WLAN_ACTION_WNM; 812 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 813 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 814 mgmt->u.action.u.bss_tm_req.req_mode = req_mode; 815 mgmt->u.action.u.bss_tm_req.disassoc_timer = 816 host_to_le16(disassoc_timer); 817 mgmt->u.action.u.bss_tm_req.validity_interval = valid_int; 818 819 pos = mgmt->u.action.u.bss_tm_req.variable; 820 821 if ((req_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) && 822 bss_term_dur) { 823 os_memcpy(pos, bss_term_dur, 12); 824 pos += 12; 825 } 826 827 if (url) { 828 /* Session Information URL */ 829 url_len = os_strlen(url); 830 if (url_len > 255) { 831 os_free(buf); 832 return -1; 833 } 834 835 *pos++ = url_len; 836 os_memcpy(pos, url, url_len); 837 pos += url_len; 838 } 839 840 if (nei_rep) { 841 os_memcpy(pos, nei_rep, nei_rep_len); 842 pos += nei_rep_len; 843 } 844 845 if (mbo_len > 0) { 846 pos += mbo_add_ie(pos, buf + sizeof(buf) - pos, mbo_attrs, 847 mbo_len); 848 } 849 850 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { 851 wpa_printf(MSG_DEBUG, 852 "Failed to send BSS Transition Management Request frame"); 853 os_free(buf); 854 return -1; 855 } 856 os_free(buf); 857 858 if (disassoc_timer) { 859 /* send disassociation frame after time-out */ 860 set_disassoc_timer(hapd, sta, disassoc_timer); 861 } 862 863 return 0; 864 } 865 866 867 int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta, 868 unsigned int auto_report, unsigned int timeout) 869 { 870 u8 buf[100], *pos; 871 struct ieee80211_mgmt *mgmt; 872 u8 dialog_token = 1; 873 874 if (auto_report > 3 || timeout > 63) 875 return -1; 876 os_memset(buf, 0, sizeof(buf)); 877 mgmt = (struct ieee80211_mgmt *) buf; 878 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 879 WLAN_FC_STYPE_ACTION); 880 os_memcpy(mgmt->da, sta->addr, ETH_ALEN); 881 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 882 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 883 mgmt->u.action.category = WLAN_ACTION_WNM; 884 mgmt->u.action.u.coloc_intf_req.action = 885 WNM_COLLOCATED_INTERFERENCE_REQ; 886 mgmt->u.action.u.coloc_intf_req.dialog_token = dialog_token; 887 mgmt->u.action.u.coloc_intf_req.req_info = auto_report | (timeout << 2); 888 pos = &mgmt->u.action.u.coloc_intf_req.req_info; 889 pos++; 890 891 wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to " 892 MACSTR " (dialog_token=%u auto_report=%u timeout=%u)", 893 MAC2STR(sta->addr), dialog_token, auto_report, timeout); 894 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) { 895 wpa_printf(MSG_DEBUG, 896 "WNM: Failed to send Collocated Interference Request frame"); 897 return -1; 898 } 899 900 return 0; 901 } 902