1 /* 2 * hostapd / IEEE 802.11 Management 3 * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 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 "common/ieee802_11_defs.h" 13 #include "hostapd.h" 14 #include "sta_info.h" 15 #include "ap_config.h" 16 #include "ap_drv_ops.h" 17 #include "ieee802_11.h" 18 19 20 #ifdef CONFIG_IEEE80211W 21 22 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, 23 struct sta_info *sta, u8 *eid) 24 { 25 u8 *pos = eid; 26 u32 timeout, tu; 27 struct os_reltime now, passed; 28 29 *pos++ = WLAN_EID_TIMEOUT_INTERVAL; 30 *pos++ = 5; 31 *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; 32 os_get_reltime(&now); 33 os_reltime_sub(&now, &sta->sa_query_start, &passed); 34 tu = (passed.sec * 1000000 + passed.usec) / 1024; 35 if (hapd->conf->assoc_sa_query_max_timeout > tu) 36 timeout = hapd->conf->assoc_sa_query_max_timeout - tu; 37 else 38 timeout = 0; 39 if (timeout < hapd->conf->assoc_sa_query_max_timeout) 40 timeout++; /* add some extra time for local timers */ 41 WPA_PUT_LE32(pos, timeout); 42 pos += 4; 43 44 return pos; 45 } 46 47 48 /* MLME-SAQuery.request */ 49 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, 50 const u8 *addr, const u8 *trans_id) 51 { 52 struct ieee80211_mgmt mgmt; 53 u8 *end; 54 55 wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " 56 MACSTR, MAC2STR(addr)); 57 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 58 trans_id, WLAN_SA_QUERY_TR_ID_LEN); 59 60 os_memset(&mgmt, 0, sizeof(mgmt)); 61 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 62 WLAN_FC_STYPE_ACTION); 63 os_memcpy(mgmt.da, addr, ETH_ALEN); 64 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); 65 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); 66 mgmt.u.action.category = WLAN_ACTION_SA_QUERY; 67 mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; 68 os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, 69 WLAN_SA_QUERY_TR_ID_LEN); 70 end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 71 if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) 72 wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed"); 73 } 74 75 76 static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, 77 const u8 *sa, const u8 *trans_id) 78 { 79 struct sta_info *sta; 80 struct ieee80211_mgmt resp; 81 u8 *end; 82 83 wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " 84 MACSTR, MAC2STR(sa)); 85 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 86 trans_id, WLAN_SA_QUERY_TR_ID_LEN); 87 88 sta = ap_get_sta(hapd, sa); 89 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { 90 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " 91 "from unassociated STA " MACSTR, MAC2STR(sa)); 92 return; 93 } 94 95 wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " 96 MACSTR, MAC2STR(sa)); 97 98 os_memset(&resp, 0, sizeof(resp)); 99 resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 100 WLAN_FC_STYPE_ACTION); 101 os_memcpy(resp.da, sa, ETH_ALEN); 102 os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); 103 os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); 104 resp.u.action.category = WLAN_ACTION_SA_QUERY; 105 resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; 106 os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, 107 WLAN_SA_QUERY_TR_ID_LEN); 108 end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; 109 if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) 110 wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed"); 111 } 112 113 114 void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, 115 const u8 action_type, const u8 *trans_id) 116 { 117 struct sta_info *sta; 118 int i; 119 120 if (action_type == WLAN_SA_QUERY_REQUEST) { 121 ieee802_11_send_sa_query_resp(hapd, sa, trans_id); 122 return; 123 } 124 125 if (action_type != WLAN_SA_QUERY_RESPONSE) { 126 wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " 127 "Action %d", action_type); 128 return; 129 } 130 131 wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " 132 MACSTR, MAC2STR(sa)); 133 wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", 134 trans_id, WLAN_SA_QUERY_TR_ID_LEN); 135 136 /* MLME-SAQuery.confirm */ 137 138 sta = ap_get_sta(hapd, sa); 139 if (sta == NULL || sta->sa_query_trans_id == NULL) { 140 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " 141 "pending SA Query request found"); 142 return; 143 } 144 145 for (i = 0; i < sta->sa_query_count; i++) { 146 if (os_memcmp(sta->sa_query_trans_id + 147 i * WLAN_SA_QUERY_TR_ID_LEN, 148 trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) 149 break; 150 } 151 152 if (i >= sta->sa_query_count) { 153 wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " 154 "transaction identifier found"); 155 return; 156 } 157 158 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, 159 HOSTAPD_LEVEL_DEBUG, 160 "Reply to pending SA Query received"); 161 ap_sta_stop_sa_query(hapd, sta); 162 } 163 164 #endif /* CONFIG_IEEE80211W */ 165 166 167 static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) 168 { 169 *pos = 0x00; 170 171 switch (idx) { 172 case 0: /* Bits 0-7 */ 173 if (hapd->iconf->obss_interval) 174 *pos |= 0x01; /* Bit 0 - Coexistence management */ 175 if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) 176 *pos |= 0x04; /* Bit 2 - Extended Channel Switching */ 177 break; 178 case 1: /* Bits 8-15 */ 179 if (hapd->conf->proxy_arp) 180 *pos |= 0x10; /* Bit 12 - Proxy ARP */ 181 if (hapd->conf->coloc_intf_reporting) { 182 /* Bit 13 - Collocated Interference Reporting */ 183 *pos |= 0x20; 184 } 185 break; 186 case 2: /* Bits 16-23 */ 187 if (hapd->conf->wnm_sleep_mode) 188 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */ 189 if (hapd->conf->bss_transition) 190 *pos |= 0x08; /* Bit 19 - BSS Transition */ 191 break; 192 case 3: /* Bits 24-31 */ 193 #ifdef CONFIG_WNM_AP 194 *pos |= 0x02; /* Bit 25 - SSID List */ 195 #endif /* CONFIG_WNM_AP */ 196 if (hapd->conf->time_advertisement == 2) 197 *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ 198 if (hapd->conf->interworking) 199 *pos |= 0x80; /* Bit 31 - Interworking */ 200 break; 201 case 4: /* Bits 32-39 */ 202 if (hapd->conf->qos_map_set_len) 203 *pos |= 0x01; /* Bit 32 - QoS Map */ 204 if (hapd->conf->tdls & TDLS_PROHIBIT) 205 *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ 206 if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) { 207 /* Bit 39 - TDLS Channel Switching Prohibited */ 208 *pos |= 0x80; 209 } 210 break; 211 case 5: /* Bits 40-47 */ 212 #ifdef CONFIG_HS20 213 if (hapd->conf->hs20) 214 *pos |= 0x40; /* Bit 46 - WNM-Notification */ 215 #endif /* CONFIG_HS20 */ 216 #ifdef CONFIG_MBO 217 if (hapd->conf->mbo_enabled) 218 *pos |= 0x40; /* Bit 46 - WNM-Notification */ 219 #endif /* CONFIG_MBO */ 220 break; 221 case 6: /* Bits 48-55 */ 222 if (hapd->conf->ssid.utf8_ssid) 223 *pos |= 0x01; /* Bit 48 - UTF-8 SSID */ 224 break; 225 case 7: /* Bits 56-63 */ 226 break; 227 case 8: /* Bits 64-71 */ 228 if (hapd->conf->ftm_responder) 229 *pos |= 0x40; /* Bit 70 - FTM responder */ 230 if (hapd->conf->ftm_initiator) 231 *pos |= 0x80; /* Bit 71 - FTM initiator */ 232 break; 233 case 9: /* Bits 72-79 */ 234 #ifdef CONFIG_FILS 235 if ((hapd->conf->wpa & WPA_PROTO_RSN) && 236 wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) 237 *pos |= 0x01; 238 #endif /* CONFIG_FILS */ 239 break; 240 } 241 } 242 243 244 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) 245 { 246 u8 *pos = eid; 247 u8 len = 0, i; 248 249 if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) 250 len = 5; 251 if (len < 4 && hapd->conf->interworking) 252 len = 4; 253 if (len < 3 && hapd->conf->wnm_sleep_mode) 254 len = 3; 255 if (len < 1 && hapd->iconf->obss_interval) 256 len = 1; 257 if (len < 7 && hapd->conf->ssid.utf8_ssid) 258 len = 7; 259 if (len < 9 && 260 (hapd->conf->ftm_initiator || hapd->conf->ftm_responder)) 261 len = 9; 262 #ifdef CONFIG_WNM_AP 263 if (len < 4) 264 len = 4; 265 #endif /* CONFIG_WNM_AP */ 266 #ifdef CONFIG_HS20 267 if (hapd->conf->hs20 && len < 6) 268 len = 6; 269 #endif /* CONFIG_HS20 */ 270 #ifdef CONFIG_MBO 271 if (hapd->conf->mbo_enabled && len < 6) 272 len = 6; 273 #endif /* CONFIG_MBO */ 274 #ifdef CONFIG_FILS 275 if ((!(hapd->conf->wpa & WPA_PROTO_RSN) || 276 !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) 277 len = 10; 278 #endif /* CONFIG_FILS */ 279 if (len < hapd->iface->extended_capa_len) 280 len = hapd->iface->extended_capa_len; 281 if (len == 0) 282 return eid; 283 284 *pos++ = WLAN_EID_EXT_CAPAB; 285 *pos++ = len; 286 for (i = 0; i < len; i++, pos++) { 287 hostapd_ext_capab_byte(hapd, pos, i); 288 289 if (i < hapd->iface->extended_capa_len) { 290 *pos &= ~hapd->iface->extended_capa_mask[i]; 291 *pos |= hapd->iface->extended_capa[i]; 292 } 293 } 294 295 while (len > 0 && eid[1 + len] == 0) { 296 len--; 297 eid[1] = len; 298 } 299 if (len == 0) 300 return eid; 301 302 return eid + 2 + len; 303 } 304 305 306 u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid) 307 { 308 u8 *pos = eid; 309 u8 len = hapd->conf->qos_map_set_len; 310 311 if (!len) 312 return eid; 313 314 *pos++ = WLAN_EID_QOS_MAP_SET; 315 *pos++ = len; 316 os_memcpy(pos, hapd->conf->qos_map_set, len); 317 pos += len; 318 319 return pos; 320 } 321 322 323 u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) 324 { 325 u8 *pos = eid; 326 #ifdef CONFIG_INTERWORKING 327 u8 *len; 328 329 if (!hapd->conf->interworking) 330 return eid; 331 332 *pos++ = WLAN_EID_INTERWORKING; 333 len = pos++; 334 335 *pos = hapd->conf->access_network_type; 336 if (hapd->conf->internet) 337 *pos |= INTERWORKING_ANO_INTERNET; 338 if (hapd->conf->asra) 339 *pos |= INTERWORKING_ANO_ASRA; 340 if (hapd->conf->esr) 341 *pos |= INTERWORKING_ANO_ESR; 342 if (hapd->conf->uesa) 343 *pos |= INTERWORKING_ANO_UESA; 344 pos++; 345 346 if (hapd->conf->venue_info_set) { 347 *pos++ = hapd->conf->venue_group; 348 *pos++ = hapd->conf->venue_type; 349 } 350 351 if (!is_zero_ether_addr(hapd->conf->hessid)) { 352 os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 353 pos += ETH_ALEN; 354 } 355 356 *len = pos - len - 1; 357 #endif /* CONFIG_INTERWORKING */ 358 359 return pos; 360 } 361 362 363 u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) 364 { 365 u8 *pos = eid; 366 #ifdef CONFIG_INTERWORKING 367 368 /* TODO: Separate configuration for ANQP? */ 369 if (!hapd->conf->interworking) 370 return eid; 371 372 *pos++ = WLAN_EID_ADV_PROTO; 373 *pos++ = 2; 374 *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ 375 *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; 376 #endif /* CONFIG_INTERWORKING */ 377 378 return pos; 379 } 380 381 382 u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) 383 { 384 u8 *pos = eid; 385 #ifdef CONFIG_INTERWORKING 386 u8 *len; 387 unsigned int i, count; 388 389 if (!hapd->conf->interworking || 390 hapd->conf->roaming_consortium == NULL || 391 hapd->conf->roaming_consortium_count == 0) 392 return eid; 393 394 *pos++ = WLAN_EID_ROAMING_CONSORTIUM; 395 len = pos++; 396 397 /* Number of ANQP OIs (in addition to the max 3 listed here) */ 398 if (hapd->conf->roaming_consortium_count > 3 + 255) 399 *pos++ = 255; 400 else if (hapd->conf->roaming_consortium_count > 3) 401 *pos++ = hapd->conf->roaming_consortium_count - 3; 402 else 403 *pos++ = 0; 404 405 /* OU #1 and #2 Lengths */ 406 *pos = hapd->conf->roaming_consortium[0].len; 407 if (hapd->conf->roaming_consortium_count > 1) 408 *pos |= hapd->conf->roaming_consortium[1].len << 4; 409 pos++; 410 411 if (hapd->conf->roaming_consortium_count > 3) 412 count = 3; 413 else 414 count = hapd->conf->roaming_consortium_count; 415 416 for (i = 0; i < count; i++) { 417 os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, 418 hapd->conf->roaming_consortium[i].len); 419 pos += hapd->conf->roaming_consortium[i].len; 420 } 421 422 *len = pos - len - 1; 423 #endif /* CONFIG_INTERWORKING */ 424 425 return pos; 426 } 427 428 429 u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) 430 { 431 if (hapd->conf->time_advertisement != 2) 432 return eid; 433 434 if (hapd->time_adv == NULL && 435 hostapd_update_time_adv(hapd) < 0) 436 return eid; 437 438 if (hapd->time_adv == NULL) 439 return eid; 440 441 os_memcpy(eid, wpabuf_head(hapd->time_adv), 442 wpabuf_len(hapd->time_adv)); 443 eid += wpabuf_len(hapd->time_adv); 444 445 return eid; 446 } 447 448 449 u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) 450 { 451 size_t len; 452 453 if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone) 454 return eid; 455 456 len = os_strlen(hapd->conf->time_zone); 457 458 *eid++ = WLAN_EID_TIME_ZONE; 459 *eid++ = len; 460 os_memcpy(eid, hapd->conf->time_zone, len); 461 eid += len; 462 463 return eid; 464 } 465 466 467 int hostapd_update_time_adv(struct hostapd_data *hapd) 468 { 469 const int elen = 2 + 1 + 10 + 5 + 1; 470 struct os_time t; 471 struct os_tm tm; 472 u8 *pos; 473 474 if (hapd->conf->time_advertisement != 2) 475 return 0; 476 477 if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) 478 return -1; 479 480 if (!hapd->time_adv) { 481 hapd->time_adv = wpabuf_alloc(elen); 482 if (hapd->time_adv == NULL) 483 return -1; 484 pos = wpabuf_put(hapd->time_adv, elen); 485 } else 486 pos = wpabuf_mhead_u8(hapd->time_adv); 487 488 *pos++ = WLAN_EID_TIME_ADVERTISEMENT; 489 *pos++ = 1 + 10 + 5 + 1; 490 491 *pos++ = 2; /* UTC time at which the TSF timer is 0 */ 492 493 /* Time Value at TSF 0 */ 494 /* FIX: need to calculate this based on the current TSF value */ 495 WPA_PUT_LE16(pos, tm.year); /* Year */ 496 pos += 2; 497 *pos++ = tm.month; /* Month */ 498 *pos++ = tm.day; /* Day of month */ 499 *pos++ = tm.hour; /* Hours */ 500 *pos++ = tm.min; /* Minutes */ 501 *pos++ = tm.sec; /* Seconds */ 502 WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ 503 pos += 2; 504 *pos++ = 0; /* Reserved */ 505 506 /* Time Error */ 507 /* TODO: fill in an estimate on the error */ 508 *pos++ = 0; 509 *pos++ = 0; 510 *pos++ = 0; 511 *pos++ = 0; 512 *pos++ = 0; 513 514 *pos++ = hapd->time_update_counter++; 515 516 return 0; 517 } 518 519 520 u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) 521 { 522 u8 *pos = eid; 523 524 #ifdef CONFIG_WNM_AP 525 if (hapd->conf->ap_max_inactivity > 0) { 526 unsigned int val; 527 *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; 528 *pos++ = 3; 529 val = hapd->conf->ap_max_inactivity; 530 if (val > 68000) 531 val = 68000; 532 val *= 1000; 533 val /= 1024; 534 if (val == 0) 535 val = 1; 536 if (val > 65535) 537 val = 65535; 538 WPA_PUT_LE16(pos, val); 539 pos += 2; 540 *pos++ = 0x00; /* TODO: Protected Keep-Alive Required */ 541 } 542 #endif /* CONFIG_WNM_AP */ 543 544 return pos; 545 } 546 547 548 #ifdef CONFIG_MBO 549 550 u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) 551 { 552 u8 mbo[9], *mbo_pos = mbo; 553 u8 *pos = eid; 554 555 if (!hapd->conf->mbo_enabled && 556 !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 557 return eid; 558 559 if (hapd->conf->mbo_enabled) { 560 *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; 561 *mbo_pos++ = 1; 562 /* Not Cellular aware */ 563 *mbo_pos++ = 0; 564 } 565 566 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { 567 *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; 568 *mbo_pos++ = 1; 569 *mbo_pos++ = hapd->mbo_assoc_disallow; 570 } 571 572 if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { 573 u8 ctrl; 574 575 ctrl = OCE_RELEASE; 576 if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 577 ctrl |= OCE_IS_STA_CFON; 578 579 *mbo_pos++ = OCE_ATTR_ID_CAPA_IND; 580 *mbo_pos++ = 1; 581 *mbo_pos++ = ctrl; 582 } 583 584 pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); 585 586 return pos; 587 } 588 589 590 u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) 591 { 592 u8 len; 593 594 if (!hapd->conf->mbo_enabled && 595 !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) 596 return 0; 597 598 /* 599 * MBO IE header (6) + Capability Indication attribute (3) + 600 * Association Disallowed attribute (3) = 12 601 */ 602 len = 6; 603 if (hapd->conf->mbo_enabled) 604 len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0); 605 606 /* OCE capability indication attribute (3) */ 607 if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) 608 len += 3; 609 610 return len; 611 } 612 613 #endif /* CONFIG_MBO */ 614 615 616 #ifdef CONFIG_OWE 617 static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd) 618 { 619 return hapd->conf->owe_transition_ssid_len > 0 && 620 !is_zero_ether_addr(hapd->conf->owe_transition_bssid); 621 } 622 #endif /* CONFIG_OWE */ 623 624 625 size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd) 626 { 627 #ifdef CONFIG_OWE 628 if (!hostapd_eid_owe_trans_enabled(hapd)) 629 return 0; 630 return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len; 631 #else /* CONFIG_OWE */ 632 return 0; 633 #endif /* CONFIG_OWE */ 634 } 635 636 637 u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, 638 size_t len) 639 { 640 #ifdef CONFIG_OWE 641 u8 *pos = eid; 642 size_t elen; 643 644 if (hapd->conf->owe_transition_ifname[0] && 645 !hostapd_eid_owe_trans_enabled(hapd)) 646 hostapd_owe_trans_get_info(hapd); 647 648 if (!hostapd_eid_owe_trans_enabled(hapd)) 649 return pos; 650 651 elen = hostapd_eid_owe_trans_len(hapd); 652 if (len < elen) { 653 wpa_printf(MSG_DEBUG, 654 "OWE: Not enough room in the buffer for OWE IE"); 655 return pos; 656 } 657 658 *pos++ = WLAN_EID_VENDOR_SPECIFIC; 659 *pos++ = elen - 2; 660 WPA_PUT_BE24(pos, OUI_WFA); 661 pos += 3; 662 *pos++ = OWE_OUI_TYPE; 663 os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN); 664 pos += ETH_ALEN; 665 *pos++ = hapd->conf->owe_transition_ssid_len; 666 os_memcpy(pos, hapd->conf->owe_transition_ssid, 667 hapd->conf->owe_transition_ssid_len); 668 pos += hapd->conf->owe_transition_ssid_len; 669 670 return pos; 671 #else /* CONFIG_OWE */ 672 return eid; 673 #endif /* CONFIG_OWE */ 674 } 675 676 677 void ap_copy_sta_supp_op_classes(struct sta_info *sta, 678 const u8 *supp_op_classes, 679 size_t supp_op_classes_len) 680 { 681 if (!supp_op_classes) 682 return; 683 os_free(sta->supp_op_classes); 684 sta->supp_op_classes = os_malloc(1 + supp_op_classes_len); 685 if (!sta->supp_op_classes) 686 return; 687 688 sta->supp_op_classes[0] = supp_op_classes_len; 689 os_memcpy(sta->supp_op_classes + 1, supp_op_classes, 690 supp_op_classes_len); 691 } 692 693 694 u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) 695 { 696 u8 *pos = eid; 697 #ifdef CONFIG_FILS 698 u8 *len; 699 u16 fils_info = 0; 700 size_t realms; 701 struct fils_realm *realm; 702 703 if (!(hapd->conf->wpa & WPA_PROTO_RSN) || 704 !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) 705 return pos; 706 707 realms = dl_list_len(&hapd->conf->fils_realms); 708 if (realms > 7) 709 realms = 7; /* 3 bit count field limits this to max 7 */ 710 711 *pos++ = WLAN_EID_FILS_INDICATION; 712 len = pos++; 713 /* TODO: B0..B2: Number of Public Key Identifiers */ 714 if (hapd->conf->erp_domain) { 715 /* B3..B5: Number of Realm Identifiers */ 716 fils_info |= realms << 3; 717 } 718 /* TODO: B6: FILS IP Address Configuration */ 719 if (hapd->conf->fils_cache_id_set) 720 fils_info |= BIT(7); 721 if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) 722 fils_info |= BIT(8); /* HESSID Included */ 723 /* FILS Shared Key Authentication without PFS Supported */ 724 fils_info |= BIT(9); 725 if (hapd->conf->fils_dh_group) { 726 /* FILS Shared Key Authentication with PFS Supported */ 727 fils_info |= BIT(10); 728 } 729 /* TODO: B11: FILS Public Key Authentication Supported */ 730 /* B12..B15: Reserved */ 731 WPA_PUT_LE16(pos, fils_info); 732 pos += 2; 733 if (hapd->conf->fils_cache_id_set) { 734 os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); 735 pos += FILS_CACHE_ID_LEN; 736 } 737 if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { 738 os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); 739 pos += ETH_ALEN; 740 } 741 742 dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, 743 list) { 744 if (realms == 0) 745 break; 746 realms--; 747 os_memcpy(pos, realm->hash, 2); 748 pos += 2; 749 } 750 *len = pos - len - 1; 751 #endif /* CONFIG_FILS */ 752 753 return pos; 754 } 755