1 /* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2018, 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 #ifndef CONFIG_NATIVE_WINDOWS 12 13 #ifdef CONFIG_TESTING_OPTIONS 14 #ifdef __NetBSD__ 15 #include <net/if_ether.h> 16 #else 17 #include <net/ethernet.h> 18 #endif 19 #include <netinet/ip.h> 20 #endif /* CONFIG_TESTING_OPTIONS */ 21 22 #include <sys/un.h> 23 #include <sys/stat.h> 24 #include <stddef.h> 25 26 #ifdef CONFIG_CTRL_IFACE_UDP 27 #include <netdb.h> 28 #endif /* CONFIG_CTRL_IFACE_UDP */ 29 30 #include "utils/common.h" 31 #include "utils/eloop.h" 32 #include "utils/module_tests.h" 33 #include "common/version.h" 34 #include "common/ieee802_11_defs.h" 35 #include "common/ctrl_iface_common.h" 36 #ifdef CONFIG_DPP 37 #include "common/dpp.h" 38 #endif /* CONFIG_DPP */ 39 #include "common/wpa_ctrl.h" 40 #include "common/ptksa_cache.h" 41 #include "common/hw_features_common.h" 42 #include "common/nan_de.h" 43 #include "crypto/tls.h" 44 #include "drivers/driver.h" 45 #include "eapol_auth/eapol_auth_sm.h" 46 #include "radius/radius_client.h" 47 #include "radius/radius_server.h" 48 #include "l2_packet/l2_packet.h" 49 #include "ap/hostapd.h" 50 #include "ap/ap_config.h" 51 #include "ap/ieee802_1x.h" 52 #include "ap/wpa_auth.h" 53 #include "ap/pmksa_cache_auth.h" 54 #include "ap/ieee802_11.h" 55 #include "ap/sta_info.h" 56 #include "ap/wps_hostapd.h" 57 #include "ap/ctrl_iface_ap.h" 58 #include "ap/ap_drv_ops.h" 59 #include "ap/hs20.h" 60 #include "ap/wnm_ap.h" 61 #include "ap/wpa_auth.h" 62 #include "ap/beacon.h" 63 #include "ap/neighbor_db.h" 64 #include "ap/rrm.h" 65 #include "ap/dpp_hostapd.h" 66 #include "ap/dfs.h" 67 #include "ap/nan_usd_ap.h" 68 #include "wps/wps_defs.h" 69 #include "wps/wps.h" 70 #include "fst/fst_ctrl_iface.h" 71 #include "config_file.h" 72 #include "ctrl_iface.h" 73 74 75 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 76 77 #ifdef CONFIG_CTRL_IFACE_UDP 78 #define HOSTAPD_CTRL_IFACE_PORT 8877 79 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50 80 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878 81 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50 82 #endif /* CONFIG_CTRL_IFACE_UDP */ 83 84 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 85 enum wpa_msg_type type, 86 const char *buf, size_t len); 87 88 89 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 90 struct sockaddr_storage *from, 91 socklen_t fromlen, const char *input) 92 { 93 return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen, input); 94 } 95 96 97 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 98 struct sockaddr_storage *from, 99 socklen_t fromlen) 100 { 101 return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen); 102 } 103 104 105 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 106 struct sockaddr_storage *from, 107 socklen_t fromlen, 108 char *level) 109 { 110 return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level); 111 } 112 113 114 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 115 const char *txtaddr) 116 { 117 u8 addr[ETH_ALEN]; 118 struct sta_info *sta; 119 120 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 121 122 if (hwaddr_aton(txtaddr, addr)) 123 return -1; 124 125 sta = ap_get_sta(hapd, addr); 126 if (sta) 127 return 0; 128 129 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 130 "notification", MAC2STR(addr)); 131 sta = ap_sta_add(hapd, addr); 132 if (sta == NULL) 133 return -1; 134 135 hostapd_new_assoc_sta(hapd, sta, 0); 136 return 0; 137 } 138 139 140 #ifdef NEED_AP_MLME 141 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 142 const char *txtaddr) 143 { 144 u8 addr[ETH_ALEN]; 145 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 146 147 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 148 149 if (hwaddr_aton(txtaddr, addr) || 150 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 151 return -1; 152 153 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 154 155 return 0; 156 } 157 #endif /* NEED_AP_MLME */ 158 159 160 #ifdef CONFIG_WPS 161 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 162 { 163 char *pin = os_strchr(txt, ' '); 164 char *timeout_txt; 165 int timeout; 166 u8 addr_buf[ETH_ALEN], *addr = NULL; 167 char *pos; 168 169 if (pin == NULL) 170 return -1; 171 *pin++ = '\0'; 172 173 timeout_txt = os_strchr(pin, ' '); 174 if (timeout_txt) { 175 *timeout_txt++ = '\0'; 176 timeout = atoi(timeout_txt); 177 pos = os_strchr(timeout_txt, ' '); 178 if (pos) { 179 *pos++ = '\0'; 180 if (hwaddr_aton(pos, addr_buf) == 0) 181 addr = addr_buf; 182 } 183 } else 184 timeout = 0; 185 186 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 187 } 188 189 190 static int hostapd_ctrl_iface_wps_check_pin( 191 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 192 { 193 char pin[9]; 194 size_t len; 195 char *pos; 196 int ret; 197 198 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 199 (u8 *) cmd, os_strlen(cmd)); 200 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 201 if (*pos < '0' || *pos > '9') 202 continue; 203 pin[len++] = *pos; 204 if (len == 9) { 205 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 206 return -1; 207 } 208 } 209 if (len != 4 && len != 8) { 210 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 211 return -1; 212 } 213 pin[len] = '\0'; 214 215 if (len == 8) { 216 unsigned int pin_val; 217 pin_val = atoi(pin); 218 if (!wps_pin_valid(pin_val)) { 219 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 220 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 221 if (os_snprintf_error(buflen, ret)) 222 return -1; 223 return ret; 224 } 225 } 226 227 ret = os_snprintf(buf, buflen, "%s", pin); 228 if (os_snprintf_error(buflen, ret)) 229 return -1; 230 231 return ret; 232 } 233 234 235 #ifdef CONFIG_WPS_NFC 236 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 237 char *pos) 238 { 239 size_t len; 240 struct wpabuf *buf; 241 int ret; 242 243 len = os_strlen(pos); 244 if (len & 0x01) 245 return -1; 246 len /= 2; 247 248 buf = wpabuf_alloc(len); 249 if (buf == NULL) 250 return -1; 251 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 252 wpabuf_free(buf); 253 return -1; 254 } 255 256 ret = hostapd_wps_nfc_tag_read(hapd, buf); 257 wpabuf_free(buf); 258 259 return ret; 260 } 261 262 263 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 264 char *cmd, char *reply, 265 size_t max_len) 266 { 267 int ndef; 268 struct wpabuf *buf; 269 int res; 270 271 if (os_strcmp(cmd, "WPS") == 0) 272 ndef = 0; 273 else if (os_strcmp(cmd, "NDEF") == 0) 274 ndef = 1; 275 else 276 return -1; 277 278 buf = hostapd_wps_nfc_config_token(hapd, ndef); 279 if (buf == NULL) 280 return -1; 281 282 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 283 wpabuf_len(buf)); 284 reply[res++] = '\n'; 285 reply[res] = '\0'; 286 287 wpabuf_free(buf); 288 289 return res; 290 } 291 292 293 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 294 char *reply, size_t max_len, 295 int ndef) 296 { 297 struct wpabuf *buf; 298 int res; 299 300 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 301 if (buf == NULL) 302 return -1; 303 304 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 305 wpabuf_len(buf)); 306 reply[res++] = '\n'; 307 reply[res] = '\0'; 308 309 wpabuf_free(buf); 310 311 return res; 312 } 313 314 315 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 316 char *cmd, char *reply, 317 size_t max_len) 318 { 319 if (os_strcmp(cmd, "WPS") == 0) 320 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 321 max_len, 0); 322 323 if (os_strcmp(cmd, "NDEF") == 0) 324 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 325 max_len, 1); 326 327 if (os_strcmp(cmd, "enable") == 0) 328 return hostapd_wps_nfc_token_enable(hapd); 329 330 if (os_strcmp(cmd, "disable") == 0) { 331 hostapd_wps_nfc_token_disable(hapd); 332 return 0; 333 } 334 335 return -1; 336 } 337 338 339 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 340 char *cmd, char *reply, 341 size_t max_len) 342 { 343 struct wpabuf *buf; 344 int res; 345 char *pos; 346 int ndef; 347 348 pos = os_strchr(cmd, ' '); 349 if (pos == NULL) 350 return -1; 351 *pos++ = '\0'; 352 353 if (os_strcmp(cmd, "WPS") == 0) 354 ndef = 0; 355 else if (os_strcmp(cmd, "NDEF") == 0) 356 ndef = 1; 357 else 358 return -1; 359 360 if (os_strcmp(pos, "WPS-CR") == 0) 361 buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 362 else 363 buf = NULL; 364 if (buf == NULL) 365 return -1; 366 367 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 368 wpabuf_len(buf)); 369 reply[res++] = '\n'; 370 reply[res] = '\0'; 371 372 wpabuf_free(buf); 373 374 return res; 375 } 376 377 378 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 379 char *cmd) 380 { 381 size_t len; 382 struct wpabuf *req, *sel; 383 int ret; 384 char *pos, *role, *type, *pos2; 385 386 role = cmd; 387 pos = os_strchr(role, ' '); 388 if (pos == NULL) 389 return -1; 390 *pos++ = '\0'; 391 392 type = pos; 393 pos = os_strchr(type, ' '); 394 if (pos == NULL) 395 return -1; 396 *pos++ = '\0'; 397 398 pos2 = os_strchr(pos, ' '); 399 if (pos2 == NULL) 400 return -1; 401 *pos2++ = '\0'; 402 403 len = os_strlen(pos); 404 if (len & 0x01) 405 return -1; 406 len /= 2; 407 408 req = wpabuf_alloc(len); 409 if (req == NULL) 410 return -1; 411 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 412 wpabuf_free(req); 413 return -1; 414 } 415 416 len = os_strlen(pos2); 417 if (len & 0x01) { 418 wpabuf_free(req); 419 return -1; 420 } 421 len /= 2; 422 423 sel = wpabuf_alloc(len); 424 if (sel == NULL) { 425 wpabuf_free(req); 426 return -1; 427 } 428 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 429 wpabuf_free(req); 430 wpabuf_free(sel); 431 return -1; 432 } 433 434 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 435 ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 436 } else { 437 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 438 "reported: role=%s type=%s", role, type); 439 ret = -1; 440 } 441 wpabuf_free(req); 442 wpabuf_free(sel); 443 444 return ret; 445 } 446 447 #endif /* CONFIG_WPS_NFC */ 448 449 450 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 451 char *buf, size_t buflen) 452 { 453 int timeout = 300; 454 char *pos; 455 const char *pin_txt; 456 457 pos = os_strchr(txt, ' '); 458 if (pos) 459 *pos++ = '\0'; 460 461 if (os_strcmp(txt, "disable") == 0) { 462 hostapd_wps_ap_pin_disable(hapd); 463 return os_snprintf(buf, buflen, "OK\n"); 464 } 465 466 if (os_strcmp(txt, "random") == 0) { 467 if (pos) 468 timeout = atoi(pos); 469 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 470 if (pin_txt == NULL) 471 return -1; 472 return os_snprintf(buf, buflen, "%s", pin_txt); 473 } 474 475 if (os_strcmp(txt, "get") == 0) { 476 pin_txt = hostapd_wps_ap_pin_get(hapd); 477 if (pin_txt == NULL) 478 return -1; 479 return os_snprintf(buf, buflen, "%s", pin_txt); 480 } 481 482 if (os_strcmp(txt, "set") == 0) { 483 char *pin; 484 if (pos == NULL) 485 return -1; 486 pin = pos; 487 pos = os_strchr(pos, ' '); 488 if (pos) { 489 *pos++ = '\0'; 490 timeout = atoi(pos); 491 } 492 if (os_strlen(pin) > buflen) 493 return -1; 494 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 495 return -1; 496 return os_snprintf(buf, buflen, "%s", pin); 497 } 498 499 return -1; 500 } 501 502 503 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 504 { 505 char *pos; 506 char *ssid, *auth, *encr = NULL, *key = NULL; 507 508 ssid = txt; 509 pos = os_strchr(txt, ' '); 510 if (!pos) 511 return -1; 512 *pos++ = '\0'; 513 514 auth = pos; 515 pos = os_strchr(pos, ' '); 516 if (pos) { 517 *pos++ = '\0'; 518 encr = pos; 519 pos = os_strchr(pos, ' '); 520 if (pos) { 521 *pos++ = '\0'; 522 key = pos; 523 } 524 } 525 526 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 527 } 528 529 530 static const char * pbc_status_str(enum pbc_status status) 531 { 532 switch (status) { 533 case WPS_PBC_STATUS_DISABLE: 534 return "Disabled"; 535 case WPS_PBC_STATUS_ACTIVE: 536 return "Active"; 537 case WPS_PBC_STATUS_TIMEOUT: 538 return "Timed-out"; 539 case WPS_PBC_STATUS_OVERLAP: 540 return "Overlap"; 541 default: 542 return "Unknown"; 543 } 544 } 545 546 547 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, 548 char *buf, size_t buflen) 549 { 550 int ret; 551 char *pos, *end; 552 553 pos = buf; 554 end = buf + buflen; 555 556 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", 557 pbc_status_str(hapd->wps_stats.pbc_status)); 558 559 if (os_snprintf_error(end - pos, ret)) 560 return pos - buf; 561 pos += ret; 562 563 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 564 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 565 "Success": 566 (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 567 "Failed" : "None"))); 568 569 if (os_snprintf_error(end - pos, ret)) 570 return pos - buf; 571 pos += ret; 572 573 /* If status == Failure - Add possible Reasons */ 574 if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 575 hapd->wps_stats.failure_reason > 0) { 576 ret = os_snprintf(pos, end - pos, 577 "Failure Reason: %s\n", 578 wps_ei_str(hapd->wps_stats.failure_reason)); 579 580 if (os_snprintf_error(end - pos, ret)) 581 return pos - buf; 582 pos += ret; 583 } 584 585 if (hapd->wps_stats.status) { 586 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 587 MAC2STR(hapd->wps_stats.peer_addr)); 588 589 if (os_snprintf_error(end - pos, ret)) 590 return pos - buf; 591 pos += ret; 592 } 593 594 return pos - buf; 595 } 596 597 #endif /* CONFIG_WPS */ 598 599 #ifdef CONFIG_HS20 600 601 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 602 const char *cmd) 603 { 604 u8 addr[ETH_ALEN]; 605 const char *url; 606 607 if (hwaddr_aton(cmd, addr)) 608 return -1; 609 url = cmd + 17; 610 if (*url == '\0') { 611 url = NULL; 612 } else { 613 if (*url != ' ') 614 return -1; 615 url++; 616 if (*url == '\0') 617 url = NULL; 618 } 619 620 return hs20_send_wnm_notification(hapd, addr, 1, url); 621 } 622 623 624 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 625 const char *cmd) 626 { 627 u8 addr[ETH_ALEN]; 628 int code, reauth_delay, ret; 629 const char *pos; 630 size_t url_len; 631 struct wpabuf *req; 632 633 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 634 if (hwaddr_aton(cmd, addr)) 635 return -1; 636 637 pos = os_strchr(cmd, ' '); 638 if (pos == NULL) 639 return -1; 640 pos++; 641 code = atoi(pos); 642 643 pos = os_strchr(pos, ' '); 644 if (pos == NULL) 645 return -1; 646 pos++; 647 reauth_delay = atoi(pos); 648 649 url_len = 0; 650 pos = os_strchr(pos, ' '); 651 if (pos) { 652 pos++; 653 url_len = os_strlen(pos); 654 } 655 656 req = wpabuf_alloc(4 + url_len); 657 if (req == NULL) 658 return -1; 659 wpabuf_put_u8(req, code); 660 wpabuf_put_le16(req, reauth_delay); 661 wpabuf_put_u8(req, url_len); 662 if (pos) 663 wpabuf_put_data(req, pos, url_len); 664 665 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 666 " to indicate imminent deauthentication (code=%d " 667 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 668 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 669 wpabuf_free(req); 670 return ret; 671 } 672 673 #endif /* CONFIG_HS20 */ 674 675 676 #ifdef CONFIG_INTERWORKING 677 678 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 679 const char *cmd) 680 { 681 u8 qos_map_set[16 + 2 * 21], count = 0; 682 const char *pos = cmd; 683 int val, ret; 684 685 for (;;) { 686 if (count == sizeof(qos_map_set)) { 687 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 688 return -1; 689 } 690 691 val = atoi(pos); 692 if (val < 0 || val > 255) { 693 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 694 return -1; 695 } 696 697 qos_map_set[count++] = val; 698 pos = os_strchr(pos, ','); 699 if (!pos) 700 break; 701 pos++; 702 } 703 704 if (count < 16 || count & 1) { 705 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 706 return -1; 707 } 708 709 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 710 if (ret) { 711 wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 712 return -1; 713 } 714 715 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 716 hapd->conf->qos_map_set_len = count; 717 718 return 0; 719 } 720 721 722 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 723 const char *cmd) 724 { 725 u8 addr[ETH_ALEN]; 726 struct sta_info *sta; 727 struct wpabuf *buf; 728 u8 *qos_map_set = hapd->conf->qos_map_set; 729 u8 qos_map_set_len = hapd->conf->qos_map_set_len; 730 int ret; 731 732 if (!qos_map_set_len) { 733 wpa_printf(MSG_INFO, "QoS Map Set is not set"); 734 return -1; 735 } 736 737 if (hwaddr_aton(cmd, addr)) 738 return -1; 739 740 sta = ap_get_sta(hapd, addr); 741 if (sta == NULL) { 742 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 743 "for QoS Map Configuration message", 744 MAC2STR(addr)); 745 return -1; 746 } 747 748 if (!sta->qos_map_enabled) { 749 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 750 "support for QoS Map", MAC2STR(addr)); 751 return -1; 752 } 753 754 buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 755 if (buf == NULL) 756 return -1; 757 758 wpabuf_put_u8(buf, WLAN_ACTION_QOS); 759 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 760 761 /* QoS Map Set Element */ 762 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 763 wpabuf_put_u8(buf, qos_map_set_len); 764 wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 765 766 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 767 wpabuf_head(buf), wpabuf_len(buf)); 768 wpabuf_free(buf); 769 770 return ret; 771 } 772 773 #endif /* CONFIG_INTERWORKING */ 774 775 776 #ifdef CONFIG_WNM_AP 777 778 static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd, 779 const char *cmd) 780 { 781 u8 addr[ETH_ALEN]; 782 struct sta_info *sta; 783 const char *pos; 784 unsigned int auto_report, timeout; 785 786 if (hwaddr_aton(cmd, addr)) { 787 wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 788 return -1; 789 } 790 791 sta = ap_get_sta(hapd, addr); 792 if (!sta) { 793 wpa_printf(MSG_DEBUG, "Station " MACSTR 794 " not found for Collocated Interference Request", 795 MAC2STR(addr)); 796 return -1; 797 } 798 799 pos = cmd + 17; 800 if (*pos != ' ') 801 return -1; 802 pos++; 803 auto_report = atoi(pos); 804 pos = os_strchr(pos, ' '); 805 if (!pos) 806 return -1; 807 pos++; 808 timeout = atoi(pos); 809 810 return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout); 811 } 812 813 #endif /* CONFIG_WNM_AP */ 814 815 816 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, 817 char *buf, size_t buflen) 818 { 819 int ret = 0; 820 char *pos, *end; 821 822 pos = buf; 823 end = buf + buflen; 824 825 WPA_ASSERT(hapd->conf->wpa_key_mgmt); 826 827 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 828 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 829 if (os_snprintf_error(end - pos, ret)) 830 return pos - buf; 831 pos += ret; 832 } 833 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 834 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 835 if (os_snprintf_error(end - pos, ret)) 836 return pos - buf; 837 pos += ret; 838 } 839 #ifdef CONFIG_IEEE80211R_AP 840 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 841 ret = os_snprintf(pos, end - pos, "FT-PSK "); 842 if (os_snprintf_error(end - pos, ret)) 843 return pos - buf; 844 pos += ret; 845 } 846 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 847 ret = os_snprintf(pos, end - pos, "FT-EAP "); 848 if (os_snprintf_error(end - pos, ret)) 849 return pos - buf; 850 pos += ret; 851 } 852 #ifdef CONFIG_SHA384 853 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { 854 ret = os_snprintf(pos, end - pos, "FT-EAP-SHA384 "); 855 if (os_snprintf_error(end - pos, ret)) 856 return pos - buf; 857 pos += ret; 858 } 859 #endif /* CONFIG_SHA384 */ 860 #ifdef CONFIG_SAE 861 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 862 ret = os_snprintf(pos, end - pos, "FT-SAE "); 863 if (os_snprintf_error(end - pos, ret)) 864 return pos - buf; 865 pos += ret; 866 } 867 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE_EXT_KEY) { 868 ret = os_snprintf(pos, end - pos, "FT-SAE-EXT-KEY "); 869 if (os_snprintf_error(end - pos, ret)) 870 return pos - buf; 871 pos += ret; 872 } 873 #endif /* CONFIG_SAE */ 874 #ifdef CONFIG_FILS 875 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 876 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 "); 877 if (os_snprintf_error(end - pos, ret)) 878 return pos - buf; 879 pos += ret; 880 } 881 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 882 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 "); 883 if (os_snprintf_error(end - pos, ret)) 884 return pos - buf; 885 pos += ret; 886 } 887 #endif /* CONFIG_FILS */ 888 #endif /* CONFIG_IEEE80211R_AP */ 889 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 890 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 891 if (os_snprintf_error(end - pos, ret)) 892 return pos - buf; 893 pos += ret; 894 } 895 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 896 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 897 if (os_snprintf_error(end - pos, ret)) 898 return pos - buf; 899 pos += ret; 900 } 901 #ifdef CONFIG_SAE 902 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 903 ret = os_snprintf(pos, end - pos, "SAE "); 904 if (os_snprintf_error(end - pos, ret)) 905 return pos - buf; 906 pos += ret; 907 } 908 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) { 909 ret = os_snprintf(pos, end - pos, "SAE-EXT-KEY "); 910 if (os_snprintf_error(end - pos, ret)) 911 return pos - buf; 912 pos += ret; 913 } 914 #endif /* CONFIG_SAE */ 915 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 916 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); 917 if (os_snprintf_error(end - pos, ret)) 918 return pos - buf; 919 pos += ret; 920 } 921 if (hapd->conf->wpa_key_mgmt & 922 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 923 ret = os_snprintf(pos, end - pos, 924 "WPA-EAP-SUITE-B-192 "); 925 if (os_snprintf_error(end - pos, ret)) 926 return pos - buf; 927 pos += ret; 928 } 929 #ifdef CONFIG_FILS 930 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 931 ret = os_snprintf(pos, end - pos, "FILS-SHA256 "); 932 if (os_snprintf_error(end - pos, ret)) 933 return pos - buf; 934 pos += ret; 935 } 936 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 937 ret = os_snprintf(pos, end - pos, "FILS-SHA384 "); 938 if (os_snprintf_error(end - pos, ret)) 939 return pos - buf; 940 pos += ret; 941 } 942 #endif /* CONFIG_FILS */ 943 944 #ifdef CONFIG_OWE 945 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) { 946 ret = os_snprintf(pos, end - pos, "OWE "); 947 if (os_snprintf_error(end - pos, ret)) 948 return pos - buf; 949 pos += ret; 950 } 951 #endif /* CONFIG_OWE */ 952 953 #ifdef CONFIG_DPP 954 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) { 955 ret = os_snprintf(pos, end - pos, "DPP "); 956 if (os_snprintf_error(end - pos, ret)) 957 return pos - buf; 958 pos += ret; 959 } 960 #endif /* CONFIG_DPP */ 961 #ifdef CONFIG_SHA384 962 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA384) { 963 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA384 "); 964 if (os_snprintf_error(end - pos, ret)) 965 return pos - buf; 966 pos += ret; 967 } 968 #endif /* CONFIG_SHA384 */ 969 970 if (pos > buf && *(pos - 1) == ' ') { 971 *(pos - 1) = '\0'; 972 pos--; 973 } 974 975 return pos - buf; 976 } 977 978 979 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 980 char *buf, size_t buflen) 981 { 982 int ret; 983 char *pos, *end; 984 985 pos = buf; 986 end = buf + buflen; 987 988 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 989 "ssid=%s\n", 990 MAC2STR(hapd->own_addr), 991 wpa_ssid_txt(hapd->conf->ssid.ssid, 992 hapd->conf->ssid.ssid_len)); 993 if (os_snprintf_error(end - pos, ret)) 994 return pos - buf; 995 pos += ret; 996 997 if ((hapd->conf->config_id)) { 998 ret = os_snprintf(pos, end - pos, "config_id=%s\n", 999 hapd->conf->config_id); 1000 if (os_snprintf_error(end - pos, ret)) 1001 return pos - buf; 1002 pos += ret; 1003 } 1004 1005 #ifdef CONFIG_WPS 1006 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 1007 hapd->conf->wps_state == 0 ? "disabled" : 1008 (hapd->conf->wps_state == 1 ? "not configured" : 1009 "configured")); 1010 if (os_snprintf_error(end - pos, ret)) 1011 return pos - buf; 1012 pos += ret; 1013 1014 if (hapd->conf->wps_state && hapd->conf->wpa && 1015 hapd->conf->ssid.wpa_passphrase) { 1016 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 1017 hapd->conf->ssid.wpa_passphrase); 1018 if (os_snprintf_error(end - pos, ret)) 1019 return pos - buf; 1020 pos += ret; 1021 } 1022 1023 if (hapd->conf->wps_state && hapd->conf->wpa && 1024 hapd->conf->ssid.wpa_psk && 1025 hapd->conf->ssid.wpa_psk->group) { 1026 char hex[PMK_LEN * 2 + 1]; 1027 wpa_snprintf_hex(hex, sizeof(hex), 1028 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 1029 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 1030 if (os_snprintf_error(end - pos, ret)) 1031 return pos - buf; 1032 pos += ret; 1033 } 1034 1035 if (hapd->conf->multi_ap) { 1036 struct hostapd_ssid *ssid = &hapd->conf->multi_ap_backhaul_ssid; 1037 1038 ret = os_snprintf(pos, end - pos, "multi_ap=%d\n", 1039 hapd->conf->multi_ap); 1040 if (os_snprintf_error(end - pos, ret)) 1041 return pos - buf; 1042 pos += ret; 1043 1044 if (ssid->ssid_len) { 1045 ret = os_snprintf(pos, end - pos, 1046 "multi_ap_backhaul_ssid=%s\n", 1047 wpa_ssid_txt(ssid->ssid, 1048 ssid->ssid_len)); 1049 if (os_snprintf_error(end - pos, ret)) 1050 return pos - buf; 1051 pos += ret; 1052 } 1053 1054 if (hapd->conf->wps_state && hapd->conf->wpa && 1055 ssid->wpa_passphrase) { 1056 ret = os_snprintf(pos, end - pos, 1057 "multi_ap_backhaul_wpa_passphrase=%s\n", 1058 ssid->wpa_passphrase); 1059 if (os_snprintf_error(end - pos, ret)) 1060 return pos - buf; 1061 pos += ret; 1062 } 1063 1064 if (hapd->conf->wps_state && hapd->conf->wpa && 1065 ssid->wpa_psk && 1066 ssid->wpa_psk->group) { 1067 char hex[PMK_LEN * 2 + 1]; 1068 1069 wpa_snprintf_hex(hex, sizeof(hex), ssid->wpa_psk->psk, 1070 PMK_LEN); 1071 ret = os_snprintf(pos, end - pos, 1072 "multi_ap_backhaul_wpa_psk=%s\n", 1073 hex); 1074 forced_memzero(hex, sizeof(hex)); 1075 if (os_snprintf_error(end - pos, ret)) 1076 return pos - buf; 1077 pos += ret; 1078 } 1079 } 1080 #endif /* CONFIG_WPS */ 1081 1082 if (hapd->conf->wpa) { 1083 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa); 1084 if (os_snprintf_error(end - pos, ret)) 1085 return pos - buf; 1086 pos += ret; 1087 } 1088 1089 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 1090 ret = os_snprintf(pos, end - pos, "key_mgmt="); 1091 if (os_snprintf_error(end - pos, ret)) 1092 return pos - buf; 1093 pos += ret; 1094 1095 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos); 1096 1097 ret = os_snprintf(pos, end - pos, "\n"); 1098 if (os_snprintf_error(end - pos, ret)) 1099 return pos - buf; 1100 pos += ret; 1101 } 1102 1103 if (hapd->conf->wpa) { 1104 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 1105 wpa_cipher_txt(hapd->conf->wpa_group)); 1106 if (os_snprintf_error(end - pos, ret)) 1107 return pos - buf; 1108 pos += ret; 1109 } 1110 1111 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 1112 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 1113 if (os_snprintf_error(end - pos, ret)) 1114 return pos - buf; 1115 pos += ret; 1116 1117 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 1118 " "); 1119 if (ret < 0) 1120 return pos - buf; 1121 pos += ret; 1122 1123 ret = os_snprintf(pos, end - pos, "\n"); 1124 if (os_snprintf_error(end - pos, ret)) 1125 return pos - buf; 1126 pos += ret; 1127 } 1128 1129 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1130 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1131 if (os_snprintf_error(end - pos, ret)) 1132 return pos - buf; 1133 pos += ret; 1134 1135 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1136 " "); 1137 if (ret < 0) 1138 return pos - buf; 1139 pos += ret; 1140 1141 ret = os_snprintf(pos, end - pos, "\n"); 1142 if (os_snprintf_error(end - pos, ret)) 1143 return pos - buf; 1144 pos += ret; 1145 } 1146 1147 if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) { 1148 ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n", 1149 hapd->conf->wpa_deny_ptk0_rekey); 1150 if (os_snprintf_error(end - pos, ret)) 1151 return pos - buf; 1152 pos += ret; 1153 } 1154 1155 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) { 1156 ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n", 1157 hapd->conf->extended_key_id); 1158 if (os_snprintf_error(end - pos, ret)) 1159 return pos - buf; 1160 pos += ret; 1161 } 1162 1163 return pos - buf; 1164 } 1165 1166 1167 static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd, 1168 const char *bands) 1169 { 1170 union wpa_event_data event; 1171 u32 setband_mask = WPA_SETBAND_AUTO; 1172 1173 /* 1174 * For example: 1175 * SET setband 2G,6G 1176 * SET setband 5G 1177 * SET setband AUTO 1178 */ 1179 if (!os_strstr(bands, "AUTO")) { 1180 if (os_strstr(bands, "5G")) 1181 setband_mask |= WPA_SETBAND_5G; 1182 if (os_strstr(bands, "6G")) 1183 setband_mask |= WPA_SETBAND_6G; 1184 if (os_strstr(bands, "2G")) 1185 setband_mask |= WPA_SETBAND_2G; 1186 if (setband_mask == WPA_SETBAND_AUTO) 1187 return -1; 1188 } 1189 1190 if (hostapd_drv_set_band(hapd, setband_mask) == 0) { 1191 os_memset(&event, 0, sizeof(event)); 1192 event.channel_list_changed.initiator = REGDOM_SET_BY_USER; 1193 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; 1194 wpa_supplicant_event(hapd, EVENT_CHANNEL_LIST_CHANGED, &event); 1195 } 1196 1197 return 0; 1198 } 1199 1200 1201 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1202 { 1203 char *value; 1204 int ret = 0; 1205 1206 value = os_strchr(cmd, ' '); 1207 if (value == NULL) 1208 return -1; 1209 *value++ = '\0'; 1210 1211 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1212 if (0) { 1213 #ifdef CONFIG_WPS_TESTING 1214 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1215 long int val; 1216 val = strtol(value, NULL, 0); 1217 if (val < 0 || val > 0xff) { 1218 ret = -1; 1219 wpa_printf(MSG_DEBUG, "WPS: Invalid " 1220 "wps_version_number %ld", val); 1221 } else { 1222 wps_version_number = val; 1223 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1224 "version %u.%u", 1225 (wps_version_number & 0xf0) >> 4, 1226 wps_version_number & 0x0f); 1227 hostapd_wps_update_ie(hapd); 1228 } 1229 } else if (os_strcasecmp(cmd, "wps_testing_stub_cred") == 0) { 1230 wps_testing_stub_cred = atoi(value); 1231 wpa_printf(MSG_DEBUG, "WPS: Testing - stub_cred=%d", 1232 wps_testing_stub_cred); 1233 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1234 wps_corrupt_pkhash = atoi(value); 1235 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1236 wps_corrupt_pkhash); 1237 #endif /* CONFIG_WPS_TESTING */ 1238 #ifdef CONFIG_TESTING_OPTIONS 1239 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1240 hapd->ext_mgmt_frame_handling = atoi(value); 1241 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 1242 hapd->ext_eapol_frame_io = atoi(value); 1243 } else if (os_strcasecmp(cmd, "force_backlog_bytes") == 0) { 1244 hapd->force_backlog_bytes = atoi(value); 1245 #ifdef CONFIG_DPP 1246 } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { 1247 os_free(hapd->dpp_config_obj_override); 1248 hapd->dpp_config_obj_override = os_strdup(value); 1249 } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { 1250 os_free(hapd->dpp_discovery_override); 1251 hapd->dpp_discovery_override = os_strdup(value); 1252 } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { 1253 os_free(hapd->dpp_groups_override); 1254 hapd->dpp_groups_override = os_strdup(value); 1255 } else if (os_strcasecmp(cmd, 1256 "dpp_ignore_netaccesskey_mismatch") == 0) { 1257 hapd->dpp_ignore_netaccesskey_mismatch = atoi(value); 1258 } else if (os_strcasecmp(cmd, "dpp_test") == 0) { 1259 dpp_test = atoi(value); 1260 } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { 1261 dpp_version_override = atoi(value); 1262 #endif /* CONFIG_DPP */ 1263 #endif /* CONFIG_TESTING_OPTIONS */ 1264 #ifdef CONFIG_MBO 1265 } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) { 1266 int val; 1267 1268 if (!hapd->conf->mbo_enabled) 1269 return -1; 1270 1271 val = atoi(value); 1272 if (val < 0 || val > MBO_ASSOC_DISALLOW_REASON_LOW_RSSI) 1273 return -1; 1274 1275 hapd->mbo_assoc_disallow = val; 1276 ieee802_11_update_beacons(hapd->iface); 1277 1278 /* 1279 * TODO: Need to configure drivers that do AP MLME offload with 1280 * disallowing station logic. 1281 */ 1282 #endif /* CONFIG_MBO */ 1283 #ifdef CONFIG_DPP 1284 } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { 1285 os_free(hapd->dpp_configurator_params); 1286 hapd->dpp_configurator_params = os_strdup(value); 1287 #ifdef CONFIG_DPP2 1288 dpp_controller_set_params(hapd->iface->interfaces->dpp, value); 1289 #endif /* CONFIG_DPP2 */ 1290 } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { 1291 hapd->dpp_init_max_tries = atoi(value); 1292 } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { 1293 hapd->dpp_init_retry_time = atoi(value); 1294 } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { 1295 hapd->dpp_resp_wait_time = atoi(value); 1296 } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { 1297 hapd->dpp_resp_max_tries = atoi(value); 1298 } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { 1299 hapd->dpp_resp_retry_time = atoi(value); 1300 #endif /* CONFIG_DPP */ 1301 } else if (os_strcasecmp(cmd, "setband") == 0) { 1302 ret = hostapd_ctrl_iface_set_band(hapd, value); 1303 } else { 1304 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1305 if (ret) 1306 return ret; 1307 1308 if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1309 hostapd_disassoc_deny_mac(hapd); 1310 } else if (os_strcasecmp(cmd, "accept_mac_file") == 0) { 1311 hostapd_disassoc_accept_mac(hapd); 1312 } else if (os_strcasecmp(cmd, "ssid") == 0) { 1313 hostapd_neighbor_sync_own_report(hapd); 1314 } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 || 1315 os_strncmp(cmd, "wmm_ac_", 7) == 0) { 1316 hapd->parameter_set_count++; 1317 if (ieee802_11_update_beacons(hapd->iface)) 1318 wpa_printf(MSG_DEBUG, 1319 "Failed to update beacons with WMM parameters"); 1320 } else if (os_strcmp(cmd, "wpa_passphrase") == 0 || 1321 os_strcmp(cmd, "sae_password") == 0 || 1322 os_strcmp(cmd, "sae_pwe") == 0) { 1323 if (hapd->started) 1324 hostapd_setup_sae_pt(hapd->conf); 1325 } else if (os_strcasecmp(cmd, "transition_disable") == 0) { 1326 wpa_auth_set_transition_disable(hapd->wpa_auth, 1327 hapd->conf->transition_disable); 1328 } 1329 1330 #ifdef CONFIG_TESTING_OPTIONS 1331 if (os_strcmp(cmd, "ft_rsnxe_used") == 0) 1332 wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth, 1333 hapd->conf->ft_rsnxe_used); 1334 else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0) 1335 wpa_auth_set_ocv_override_freq( 1336 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3, 1337 atoi(value)); 1338 else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0) 1339 wpa_auth_set_ocv_override_freq( 1340 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1, 1341 atoi(value)); 1342 else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0) 1343 wpa_auth_set_ocv_override_freq( 1344 hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC, 1345 atoi(value)); 1346 else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0) 1347 wpa_auth_set_ocv_override_freq( 1348 hapd->wpa_auth, 1349 WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value)); 1350 #endif /* CONFIG_TESTING_OPTIONS */ 1351 } 1352 1353 return ret; 1354 } 1355 1356 1357 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1358 char *buf, size_t buflen) 1359 { 1360 int res; 1361 1362 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1363 1364 if (os_strcmp(cmd, "version") == 0) { 1365 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1366 if (os_snprintf_error(buflen, res)) 1367 return -1; 1368 return res; 1369 } else if (os_strcmp(cmd, "tls_library") == 0) { 1370 res = tls_get_library_version(buf, buflen); 1371 if (os_snprintf_error(buflen, res)) 1372 return -1; 1373 return res; 1374 } 1375 1376 return -1; 1377 } 1378 1379 1380 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1381 { 1382 if (hostapd_enable_iface(iface) < 0) { 1383 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1384 return -1; 1385 } 1386 return 0; 1387 } 1388 1389 1390 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1391 { 1392 if (hostapd_reload_iface(iface) < 0) { 1393 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1394 return -1; 1395 } 1396 return 0; 1397 } 1398 1399 1400 static int hostapd_ctrl_iface_reload_bss(struct hostapd_data *bss) 1401 { 1402 if (hostapd_reload_bss_only(bss) < 0) { 1403 wpa_printf(MSG_ERROR, "Reloading of BSS failed"); 1404 return -1; 1405 } 1406 return 0; 1407 } 1408 1409 1410 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1411 { 1412 if (hostapd_disable_iface(iface) < 0) { 1413 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1414 return -1; 1415 } 1416 return 0; 1417 } 1418 1419 1420 static int 1421 hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd, 1422 struct sta_info *sta, void *ctx) 1423 { 1424 struct hostapd_wpa_psk *psk; 1425 const u8 *pmk; 1426 int pmk_len; 1427 int pmk_match; 1428 int sta_match; 1429 int bss_match; 1430 int reason; 1431 1432 pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); 1433 1434 for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) { 1435 pmk_match = PMK_LEN == pmk_len && 1436 os_memcmp(psk->psk, pmk, pmk_len) == 0; 1437 sta_match = psk->group == 0 && 1438 ether_addr_equal(sta->addr, psk->addr); 1439 bss_match = psk->group == 1; 1440 1441 if (pmk_match && (sta_match || bss_match)) 1442 return 0; 1443 } 1444 1445 wpa_printf(MSG_INFO, "STA " MACSTR 1446 " PSK/passphrase no longer valid - disconnect", 1447 MAC2STR(sta->addr)); 1448 reason = WLAN_REASON_PREV_AUTH_NOT_VALID; 1449 hostapd_drv_sta_deauth(hapd, sta->addr, reason); 1450 ap_sta_deauthenticate(hapd, sta, reason); 1451 1452 return 0; 1453 } 1454 1455 1456 static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd) 1457 { 1458 struct hostapd_bss_config *conf = hapd->conf; 1459 int err; 1460 1461 hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); 1462 1463 err = hostapd_setup_wpa_psk(conf); 1464 if (err < 0) { 1465 wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d", 1466 err); 1467 return -1; 1468 } 1469 1470 ap_for_each_sta(hapd, hostapd_ctrl_iface_kick_mismatch_psk_sta_iter, 1471 NULL); 1472 1473 return 0; 1474 } 1475 1476 1477 #ifdef CONFIG_IEEE80211R_AP 1478 1479 static int hostapd_ctrl_iface_get_rxkhs(struct hostapd_data *hapd, 1480 char *buf, size_t buflen) 1481 { 1482 int ret, start_pos; 1483 char *pos, *end; 1484 struct ft_remote_r0kh *r0kh; 1485 struct ft_remote_r1kh *r1kh; 1486 struct hostapd_bss_config *conf = hapd->conf; 1487 1488 pos = buf; 1489 end = buf + buflen; 1490 1491 for (r0kh = conf->r0kh_list; r0kh; r0kh=r0kh->next) { 1492 start_pos = pos - buf; 1493 ret = os_snprintf(pos, end - pos, "r0kh=" MACSTR " ", 1494 MAC2STR(r0kh->addr)); 1495 if (os_snprintf_error(end - pos, ret)) 1496 return start_pos; 1497 pos += ret; 1498 if (r0kh->id_len + 1 >= (size_t) (end - pos)) 1499 return start_pos; 1500 os_memcpy(pos, r0kh->id, r0kh->id_len); 1501 pos += r0kh->id_len; 1502 *pos++ = ' '; 1503 pos += wpa_snprintf_hex(pos, end - pos, r0kh->key, 1504 sizeof(r0kh->key)); 1505 ret = os_snprintf(pos, end - pos, "\n"); 1506 if (os_snprintf_error(end - pos, ret)) 1507 return start_pos; 1508 pos += ret; 1509 } 1510 1511 for (r1kh = conf->r1kh_list; r1kh; r1kh=r1kh->next) { 1512 start_pos = pos - buf; 1513 ret = os_snprintf(pos, end - pos, "r1kh=" MACSTR " " MACSTR " ", 1514 MAC2STR(r1kh->addr), MAC2STR(r1kh->id)); 1515 if (os_snprintf_error(end - pos, ret)) 1516 return start_pos; 1517 pos += ret; 1518 pos += wpa_snprintf_hex(pos, end - pos, r1kh->key, 1519 sizeof(r1kh->key)); 1520 ret = os_snprintf(pos, end - pos, "\n"); 1521 if (os_snprintf_error(end - pos, ret)) 1522 return start_pos; 1523 pos += ret; 1524 } 1525 1526 return pos - buf; 1527 } 1528 1529 1530 static int hostapd_ctrl_iface_reload_rxkhs(struct hostapd_data *hapd) 1531 { 1532 struct hostapd_bss_config *conf = hapd->conf; 1533 int err; 1534 1535 hostapd_config_clear_rxkhs(conf); 1536 1537 err = hostapd_config_read_rxkh_file(conf, conf->rxkh_file); 1538 if (err < 0) { 1539 wpa_printf(MSG_ERROR, "Reloading RxKHs failed: %d", 1540 err); 1541 return -1; 1542 } 1543 1544 return 0; 1545 } 1546 1547 #endif /* CONFIG_IEEE80211R_AP */ 1548 1549 1550 #ifdef CONFIG_TESTING_OPTIONS 1551 1552 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1553 { 1554 union wpa_event_data data; 1555 char *pos, *param; 1556 enum wpa_event_type event; 1557 1558 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1559 1560 os_memset(&data, 0, sizeof(data)); 1561 1562 param = os_strchr(cmd, ' '); 1563 if (param == NULL) 1564 return -1; 1565 *param++ = '\0'; 1566 1567 if (os_strcmp(cmd, "DETECTED") == 0) 1568 event = EVENT_DFS_RADAR_DETECTED; 1569 else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1570 event = EVENT_DFS_CAC_FINISHED; 1571 else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1572 event = EVENT_DFS_CAC_ABORTED; 1573 else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1574 event = EVENT_DFS_NOP_FINISHED; 1575 else { 1576 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1577 cmd); 1578 return -1; 1579 } 1580 1581 pos = os_strstr(param, "freq="); 1582 if (pos) 1583 data.dfs_event.freq = atoi(pos + 5); 1584 1585 pos = os_strstr(param, "ht_enabled=1"); 1586 if (pos) 1587 data.dfs_event.ht_enabled = 1; 1588 1589 pos = os_strstr(param, "chan_offset="); 1590 if (pos) 1591 data.dfs_event.chan_offset = atoi(pos + 12); 1592 1593 pos = os_strstr(param, "chan_width="); 1594 if (pos) 1595 data.dfs_event.chan_width = atoi(pos + 11); 1596 1597 pos = os_strstr(param, "cf1="); 1598 if (pos) 1599 data.dfs_event.cf1 = atoi(pos + 4); 1600 1601 pos = os_strstr(param, "cf2="); 1602 if (pos) 1603 data.dfs_event.cf2 = atoi(pos + 4); 1604 1605 wpa_supplicant_event(hapd, event, &data); 1606 1607 return 0; 1608 } 1609 1610 1611 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1612 { 1613 size_t len; 1614 u8 *buf; 1615 int res; 1616 1617 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1618 1619 len = os_strlen(cmd); 1620 if (len & 1) 1621 return -1; 1622 len /= 2; 1623 1624 buf = os_malloc(len); 1625 if (buf == NULL) 1626 return -1; 1627 1628 if (hexstr2bin(cmd, buf, len) < 0) { 1629 os_free(buf); 1630 return -1; 1631 } 1632 1633 res = hostapd_drv_send_mlme(hapd, buf, len, 0, NULL, 0, 0); 1634 os_free(buf); 1635 return res; 1636 } 1637 1638 1639 static int hostapd_ctrl_iface_mgmt_tx_status_process(struct hostapd_data *hapd, 1640 char *cmd) 1641 { 1642 char *pos, *param; 1643 size_t len; 1644 u8 *buf; 1645 int stype = 0, ok = 0; 1646 union wpa_event_data event; 1647 1648 if (!hapd->ext_mgmt_frame_handling) 1649 return -1; 1650 1651 /* stype=<val> ok=<0/1> buf=<frame hexdump> */ 1652 1653 wpa_printf(MSG_DEBUG, "External MGMT TX status process: %s", cmd); 1654 1655 pos = cmd; 1656 param = os_strstr(pos, "stype="); 1657 if (param) { 1658 param += 6; 1659 stype = atoi(param); 1660 } 1661 1662 param = os_strstr(pos, " ok="); 1663 if (param) { 1664 param += 4; 1665 ok = atoi(param); 1666 } 1667 1668 param = os_strstr(pos, " buf="); 1669 if (!param) 1670 return -1; 1671 param += 5; 1672 1673 len = os_strlen(param); 1674 if (len & 1) 1675 return -1; 1676 len /= 2; 1677 1678 buf = os_malloc(len); 1679 if (!buf || hexstr2bin(param, buf, len) < 0) { 1680 os_free(buf); 1681 return -1; 1682 } 1683 1684 os_memset(&event, 0, sizeof(event)); 1685 event.tx_status.type = WLAN_FC_TYPE_MGMT; 1686 event.tx_status.data = buf; 1687 event.tx_status.data_len = len; 1688 event.tx_status.stype = stype; 1689 event.tx_status.ack = ok; 1690 hapd->ext_mgmt_frame_handling = 0; 1691 wpa_supplicant_event(hapd, EVENT_TX_STATUS, &event); 1692 hapd->ext_mgmt_frame_handling = 1; 1693 1694 os_free(buf); 1695 1696 return 0; 1697 } 1698 1699 1700 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd, 1701 char *cmd) 1702 { 1703 char *pos, *param; 1704 size_t len; 1705 u8 *buf; 1706 int freq = 0, datarate = 0, ssi_signal = 0; 1707 union wpa_event_data event; 1708 1709 if (!hapd->ext_mgmt_frame_handling) 1710 return -1; 1711 1712 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 1713 1714 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 1715 1716 pos = cmd; 1717 param = os_strstr(pos, "freq="); 1718 if (param) { 1719 param += 5; 1720 freq = atoi(param); 1721 } 1722 1723 param = os_strstr(pos, " datarate="); 1724 if (param) { 1725 param += 10; 1726 datarate = atoi(param); 1727 } 1728 1729 param = os_strstr(pos, " ssi_signal="); 1730 if (param) { 1731 param += 12; 1732 ssi_signal = atoi(param); 1733 } 1734 1735 param = os_strstr(pos, " frame="); 1736 if (param == NULL) 1737 return -1; 1738 param += 7; 1739 1740 len = os_strlen(param); 1741 if (len & 1) 1742 return -1; 1743 len /= 2; 1744 1745 buf = os_malloc(len); 1746 if (buf == NULL) 1747 return -1; 1748 1749 if (hexstr2bin(param, buf, len) < 0) { 1750 os_free(buf); 1751 return -1; 1752 } 1753 1754 os_memset(&event, 0, sizeof(event)); 1755 event.rx_mgmt.freq = freq; 1756 event.rx_mgmt.frame = buf; 1757 event.rx_mgmt.frame_len = len; 1758 event.rx_mgmt.ssi_signal = ssi_signal; 1759 event.rx_mgmt.datarate = datarate; 1760 hapd->ext_mgmt_frame_handling = 0; 1761 wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event); 1762 hapd->ext_mgmt_frame_handling = 1; 1763 1764 os_free(buf); 1765 1766 return 0; 1767 } 1768 1769 1770 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd) 1771 { 1772 char *pos; 1773 u8 src[ETH_ALEN], *buf; 1774 int used; 1775 size_t len; 1776 1777 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 1778 1779 pos = cmd; 1780 used = hwaddr_aton2(pos, src); 1781 if (used < 0) 1782 return -1; 1783 pos += used; 1784 while (*pos == ' ') 1785 pos++; 1786 1787 len = os_strlen(pos); 1788 if (len & 1) 1789 return -1; 1790 len /= 2; 1791 1792 buf = os_malloc(len); 1793 if (buf == NULL) 1794 return -1; 1795 1796 if (hexstr2bin(pos, buf, len) < 0) { 1797 os_free(buf); 1798 return -1; 1799 } 1800 1801 ieee802_1x_receive(hapd, src, buf, len, FRAME_ENCRYPTION_UNKNOWN); 1802 os_free(buf); 1803 1804 return 0; 1805 } 1806 1807 1808 static int hostapd_ctrl_iface_eapol_tx(struct hostapd_data *hapd, char *cmd) 1809 { 1810 char *pos, *pos2; 1811 u8 dst[ETH_ALEN], *buf; 1812 int used, ret; 1813 size_t len; 1814 unsigned int prev; 1815 int encrypt = 0; 1816 1817 wpa_printf(MSG_DEBUG, "External EAPOL TX: %s", cmd); 1818 1819 pos = cmd; 1820 used = hwaddr_aton2(pos, dst); 1821 if (used < 0) 1822 return -1; 1823 pos += used; 1824 while (*pos == ' ') 1825 pos++; 1826 1827 pos2 = os_strchr(pos, ' '); 1828 if (pos2) { 1829 len = pos2 - pos; 1830 encrypt = os_strstr(pos2, "encrypt=1") != NULL; 1831 } else { 1832 len = os_strlen(pos); 1833 } 1834 if (len & 1) 1835 return -1; 1836 len /= 2; 1837 1838 buf = os_malloc(len); 1839 if (!buf || hexstr2bin(pos, buf, len) < 0) { 1840 os_free(buf); 1841 return -1; 1842 } 1843 1844 prev = hapd->ext_eapol_frame_io; 1845 hapd->ext_eapol_frame_io = 0; 1846 ret = hostapd_wpa_auth_send_eapol(hapd, dst, buf, len, encrypt); 1847 hapd->ext_eapol_frame_io = prev; 1848 os_free(buf); 1849 1850 return ret; 1851 } 1852 1853 1854 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 1855 { 1856 size_t i; 1857 u32 sum = 0; 1858 const u16 *pos = buf; 1859 1860 for (i = 0; i < len / 2; i++) 1861 sum += *pos++; 1862 1863 while (sum >> 16) 1864 sum = (sum & 0xffff) + (sum >> 16); 1865 1866 return sum ^ 0xffff; 1867 } 1868 1869 1870 #define HWSIM_PACKETLEN 1500 1871 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 1872 1873 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 1874 size_t len) 1875 { 1876 struct hostapd_data *hapd = ctx; 1877 const struct ether_header *eth; 1878 struct ip ip; 1879 const u8 *pos; 1880 unsigned int i; 1881 char extra[30]; 1882 1883 if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { 1884 wpa_printf(MSG_DEBUG, 1885 "test data: RX - ignore unexpected length %d", 1886 (int) len); 1887 return; 1888 } 1889 1890 eth = (const struct ether_header *) buf; 1891 os_memcpy(&ip, eth + 1, sizeof(ip)); 1892 pos = &buf[sizeof(*eth) + sizeof(ip)]; 1893 1894 if (ip.ip_hl != 5 || ip.ip_v != 4 || 1895 ntohs(ip.ip_len) > HWSIM_IP_LEN) { 1896 wpa_printf(MSG_DEBUG, 1897 "test data: RX - ignore unexpected IP header"); 1898 return; 1899 } 1900 1901 for (i = 0; i < ntohs(ip.ip_len) - sizeof(ip); i++) { 1902 if (*pos != (u8) i) { 1903 wpa_printf(MSG_DEBUG, 1904 "test data: RX - ignore mismatching payload"); 1905 return; 1906 } 1907 pos++; 1908 } 1909 1910 extra[0] = '\0'; 1911 if (ntohs(ip.ip_len) != HWSIM_IP_LEN) 1912 os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.ip_len)); 1913 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", 1914 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); 1915 } 1916 1917 1918 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, 1919 char *cmd) 1920 { 1921 int enabled = atoi(cmd); 1922 char *pos; 1923 const char *ifname; 1924 const u8 *addr = hapd->own_addr; 1925 1926 if (!enabled) { 1927 if (hapd->l2_test) { 1928 l2_packet_deinit(hapd->l2_test); 1929 hapd->l2_test = NULL; 1930 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1931 "test data: Disabled"); 1932 } 1933 return 0; 1934 } 1935 1936 if (hapd->l2_test) 1937 return 0; 1938 1939 pos = os_strstr(cmd, " ifname="); 1940 if (pos) 1941 ifname = pos + 8; 1942 else 1943 ifname = hapd->conf->iface; 1944 1945 #ifdef CONFIG_IEEE80211BE 1946 if (hapd->conf->mld_ap) 1947 addr = hapd->mld->mld_addr; 1948 #endif /* CONFIG_IEEE80211BE */ 1949 hapd->l2_test = l2_packet_init(ifname, addr, 1950 ETHERTYPE_IP, hostapd_data_test_rx, 1951 hapd, 1); 1952 if (hapd->l2_test == NULL) 1953 return -1; 1954 1955 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled"); 1956 1957 return 0; 1958 } 1959 1960 1961 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) 1962 { 1963 u8 dst[ETH_ALEN], src[ETH_ALEN]; 1964 char *pos, *pos2; 1965 int used; 1966 long int val; 1967 u8 tos; 1968 u8 buf[2 + HWSIM_PACKETLEN]; 1969 struct ether_header *eth; 1970 struct ip *ip; 1971 u8 *dpos; 1972 unsigned int i; 1973 size_t send_len = HWSIM_IP_LEN; 1974 1975 if (hapd->l2_test == NULL) 1976 return -1; 1977 1978 /* format: <dst> <src> <tos> [len=<length>] */ 1979 1980 pos = cmd; 1981 used = hwaddr_aton2(pos, dst); 1982 if (used < 0) 1983 return -1; 1984 pos += used; 1985 while (*pos == ' ') 1986 pos++; 1987 used = hwaddr_aton2(pos, src); 1988 if (used < 0) 1989 return -1; 1990 pos += used; 1991 1992 val = strtol(pos, &pos2, 0); 1993 if (val < 0 || val > 0xff) 1994 return -1; 1995 tos = val; 1996 1997 pos = os_strstr(pos2, " len="); 1998 if (pos) { 1999 i = atoi(pos + 5); 2000 if (i < sizeof(*ip) || i > HWSIM_IP_LEN) 2001 return -1; 2002 send_len = i; 2003 } 2004 2005 eth = (struct ether_header *) &buf[2]; 2006 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 2007 os_memcpy(eth->ether_shost, src, ETH_ALEN); 2008 eth->ether_type = htons(ETHERTYPE_IP); 2009 ip = (struct ip *) (eth + 1); 2010 os_memset(ip, 0, sizeof(*ip)); 2011 ip->ip_hl = 5; 2012 ip->ip_v = 4; 2013 ip->ip_ttl = 64; 2014 ip->ip_tos = tos; 2015 ip->ip_len = htons(send_len); 2016 ip->ip_p = 1; 2017 ip->ip_src.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 2018 ip->ip_dst.s_addr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 2019 ip->ip_sum = ipv4_hdr_checksum(ip, sizeof(*ip)); 2020 dpos = (u8 *) (ip + 1); 2021 for (i = 0; i < send_len - sizeof(*ip); i++) 2022 *dpos++ = i; 2023 2024 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2], 2025 sizeof(struct ether_header) + send_len) < 0) 2026 return -1; 2027 2028 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR 2029 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 2030 2031 return 0; 2032 } 2033 2034 2035 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd, 2036 char *cmd) 2037 { 2038 u8 *buf; 2039 struct ether_header *eth; 2040 struct l2_packet_data *l2 = NULL; 2041 size_t len; 2042 u16 ethertype; 2043 int res = -1; 2044 const char *ifname = hapd->conf->iface; 2045 2046 if (os_strncmp(cmd, "ifname=", 7) == 0) { 2047 cmd += 7; 2048 ifname = cmd; 2049 cmd = os_strchr(cmd, ' '); 2050 if (cmd == NULL) 2051 return -1; 2052 *cmd++ = '\0'; 2053 } 2054 2055 len = os_strlen(cmd); 2056 if (len & 1 || len < ETH_HLEN * 2) 2057 return -1; 2058 len /= 2; 2059 2060 buf = os_malloc(len); 2061 if (buf == NULL) 2062 return -1; 2063 2064 if (hexstr2bin(cmd, buf, len) < 0) 2065 goto done; 2066 2067 eth = (struct ether_header *) buf; 2068 ethertype = ntohs(eth->ether_type); 2069 2070 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype, 2071 hostapd_data_test_rx, hapd, 1); 2072 if (l2 == NULL) 2073 goto done; 2074 2075 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 2076 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res); 2077 done: 2078 if (l2) 2079 l2_packet_deinit(l2); 2080 os_free(buf); 2081 2082 return res < 0 ? -1 : 0; 2083 } 2084 2085 2086 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) 2087 { 2088 struct sta_info *sta; 2089 u8 addr[ETH_ALEN]; 2090 u8 zero[WPA_TK_MAX_LEN]; 2091 2092 os_memset(zero, 0, sizeof(zero)); 2093 2094 if (hwaddr_aton(cmd, addr)) 2095 return -1; 2096 2097 if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) { 2098 if (hapd->last_bigtk_alg == WPA_ALG_NONE) 2099 return -1; 2100 2101 wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK"); 2102 2103 /* First, use a zero key to avoid any possible duplicate key 2104 * avoidance in the driver. */ 2105 if (hostapd_drv_set_key(hapd->conf->iface, hapd, 2106 hapd->last_bigtk_alg, 2107 broadcast_ether_addr, 2108 hapd->last_bigtk_key_idx, 0, 1, NULL, 0, 2109 zero, hapd->last_bigtk_len, 2110 KEY_FLAG_GROUP_TX_DEFAULT) < 0) 2111 return -1; 2112 2113 /* Set the previously configured key to reset its TSC */ 2114 return hostapd_drv_set_key(hapd->conf->iface, hapd, 2115 hapd->last_bigtk_alg, 2116 broadcast_ether_addr, 2117 hapd->last_bigtk_key_idx, 0, 1, NULL, 2118 0, hapd->last_bigtk, 2119 hapd->last_bigtk_len, 2120 KEY_FLAG_GROUP_TX_DEFAULT); 2121 } 2122 2123 if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) { 2124 if (hapd->last_igtk_alg == WPA_ALG_NONE) 2125 return -1; 2126 2127 wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK"); 2128 2129 /* First, use a zero key to avoid any possible duplicate key 2130 * avoidance in the driver. */ 2131 if (hostapd_drv_set_key(hapd->conf->iface, hapd, 2132 hapd->last_igtk_alg, 2133 broadcast_ether_addr, 2134 hapd->last_igtk_key_idx, 0, 1, NULL, 0, 2135 zero, hapd->last_igtk_len, 2136 KEY_FLAG_GROUP_TX_DEFAULT) < 0) 2137 return -1; 2138 2139 /* Set the previously configured key to reset its TSC */ 2140 return hostapd_drv_set_key(hapd->conf->iface, hapd, 2141 hapd->last_igtk_alg, 2142 broadcast_ether_addr, 2143 hapd->last_igtk_key_idx, 0, 1, NULL, 2144 0, hapd->last_igtk, 2145 hapd->last_igtk_len, 2146 KEY_FLAG_GROUP_TX_DEFAULT); 2147 } 2148 2149 if (is_broadcast_ether_addr(addr)) { 2150 if (hapd->last_gtk_alg == WPA_ALG_NONE) 2151 return -1; 2152 2153 wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK"); 2154 2155 /* First, use a zero key to avoid any possible duplicate key 2156 * avoidance in the driver. */ 2157 if (hostapd_drv_set_key(hapd->conf->iface, hapd, 2158 hapd->last_gtk_alg, 2159 broadcast_ether_addr, 2160 hapd->last_gtk_key_idx, 0, 1, NULL, 0, 2161 zero, hapd->last_gtk_len, 2162 KEY_FLAG_GROUP_TX_DEFAULT) < 0) 2163 return -1; 2164 2165 /* Set the previously configured key to reset its TSC */ 2166 return hostapd_drv_set_key(hapd->conf->iface, hapd, 2167 hapd->last_gtk_alg, 2168 broadcast_ether_addr, 2169 hapd->last_gtk_key_idx, 0, 1, NULL, 2170 0, hapd->last_gtk, 2171 hapd->last_gtk_len, 2172 KEY_FLAG_GROUP_TX_DEFAULT); 2173 } 2174 2175 sta = ap_get_sta(hapd, addr); 2176 if (!sta) 2177 return -1; 2178 2179 if (sta->last_tk_alg == WPA_ALG_NONE) 2180 return -1; 2181 2182 wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR, 2183 MAC2STR(sta->addr)); 2184 2185 /* First, use a zero key to avoid any possible duplicate key avoidance 2186 * in the driver. */ 2187 if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2188 sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0, 2189 zero, sta->last_tk_len, 2190 KEY_FLAG_PAIRWISE_RX_TX) < 0) 2191 return -1; 2192 2193 /* Set the previously configured key to reset its TSC/RSC */ 2194 return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2195 sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 2196 0, sta->last_tk, sta->last_tk_len, 2197 KEY_FLAG_PAIRWISE_RX_TX); 2198 } 2199 2200 2201 static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd) 2202 { 2203 u8 addr[ETH_ALEN]; 2204 const char *pos = cmd; 2205 enum wpa_alg alg; 2206 enum key_flag key_flag; 2207 int idx, set_tx; 2208 u8 seq[6], key[WPA_TK_MAX_LEN]; 2209 size_t key_len; 2210 2211 /* parameters: alg addr idx set_tx seq key key_flag */ 2212 2213 alg = atoi(pos); 2214 pos = os_strchr(pos, ' '); 2215 if (!pos) 2216 return -1; 2217 pos++; 2218 if (hwaddr_aton(pos, addr)) 2219 return -1; 2220 pos += 17; 2221 if (*pos != ' ') 2222 return -1; 2223 pos++; 2224 idx = atoi(pos); 2225 pos = os_strchr(pos, ' '); 2226 if (!pos) 2227 return -1; 2228 pos++; 2229 set_tx = atoi(pos); 2230 pos = os_strchr(pos, ' '); 2231 if (!pos) 2232 return -1; 2233 pos++; 2234 if (hexstr2bin(pos, seq, sizeof(seq)) < 0) 2235 return -1; 2236 pos += 2 * 6; 2237 if (*pos != ' ') 2238 return -1; 2239 pos++; 2240 if (!os_strchr(pos, ' ')) 2241 return -1; 2242 key_len = (os_strchr(pos, ' ') - pos) / 2; 2243 if (hexstr2bin(pos, key, key_len) < 0) 2244 return -1; 2245 pos += 2 * key_len; 2246 if (*pos != ' ') 2247 return -1; 2248 2249 pos++; 2250 key_flag = atoi(pos); 2251 pos = os_strchr(pos, ' '); 2252 if (pos) 2253 return -1; 2254 2255 wpa_printf(MSG_INFO, "TESTING: Set key"); 2256 return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx, 0, 2257 set_tx, seq, 6, key, key_len, key_flag); 2258 } 2259 2260 2261 static void restore_tk(void *ctx1, void *ctx2) 2262 { 2263 struct hostapd_data *hapd = ctx1; 2264 struct sta_info *sta = ctx2; 2265 2266 wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR, 2267 MAC2STR(sta->addr)); 2268 /* This does not really restore the TSC properly, so this will result 2269 * in replay protection issues for now since there is no clean way of 2270 * preventing encryption of a single EAPOL frame. */ 2271 hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg, 2272 sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0, 2273 sta->last_tk, sta->last_tk_len, 2274 KEY_FLAG_PAIRWISE_RX_TX); 2275 } 2276 2277 2278 static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd) 2279 { 2280 struct sta_info *sta; 2281 u8 addr[ETH_ALEN]; 2282 int plain = os_strstr(cmd, "plaintext") != NULL; 2283 2284 if (hwaddr_aton(cmd, addr)) 2285 return -1; 2286 2287 sta = ap_get_sta(hapd, addr); 2288 if (!sta || !sta->wpa_sm) 2289 return -1; 2290 2291 if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2292 plain = 0; /* no need for special processing */ 2293 if (plain) { 2294 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2295 MAC2STR(sta->addr)); 2296 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2297 sta->addr, sta->last_tk_key_idx, 0, 0, NULL, 2298 0, NULL, 0, KEY_FLAG_PAIRWISE); 2299 } 2300 2301 wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr)); 2302 return wpa_auth_resend_m1(sta->wpa_sm, 2303 os_strstr(cmd, "change-anonce") != NULL, 2304 plain ? restore_tk : NULL, hapd, sta); 2305 } 2306 2307 2308 static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd) 2309 { 2310 struct sta_info *sta; 2311 u8 addr[ETH_ALEN]; 2312 int plain = os_strstr(cmd, "plaintext") != NULL; 2313 2314 if (hwaddr_aton(cmd, addr)) 2315 return -1; 2316 2317 sta = ap_get_sta(hapd, addr); 2318 if (!sta || !sta->wpa_sm) 2319 return -1; 2320 2321 if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2322 plain = 0; /* no need for special processing */ 2323 if (plain) { 2324 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2325 MAC2STR(sta->addr)); 2326 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2327 sta->addr, sta->last_tk_key_idx, 0, 0, NULL, 2328 0, NULL, 0, KEY_FLAG_PAIRWISE); 2329 } 2330 2331 wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr)); 2332 return wpa_auth_resend_m3(sta->wpa_sm, 2333 plain ? restore_tk : NULL, hapd, sta); 2334 } 2335 2336 2337 static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd, 2338 const char *cmd) 2339 { 2340 struct sta_info *sta; 2341 u8 addr[ETH_ALEN]; 2342 int plain = os_strstr(cmd, "plaintext") != NULL; 2343 2344 if (hwaddr_aton(cmd, addr)) 2345 return -1; 2346 2347 sta = ap_get_sta(hapd, addr); 2348 if (!sta || !sta->wpa_sm) 2349 return -1; 2350 2351 if (plain && sta->last_tk_alg == WPA_ALG_NONE) 2352 plain = 0; /* no need for special processing */ 2353 if (plain) { 2354 wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR, 2355 MAC2STR(sta->addr)); 2356 hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, 2357 sta->addr, sta->last_tk_key_idx, 0, 0, NULL, 2358 0, NULL, 0, KEY_FLAG_PAIRWISE); 2359 } 2360 2361 wpa_printf(MSG_INFO, 2362 "TESTING: Send group M1 for the same GTK and zero RSC to " 2363 MACSTR, MAC2STR(sta->addr)); 2364 return wpa_auth_resend_group_m1(sta->wpa_sm, 2365 plain ? restore_tk : NULL, hapd, sta); 2366 } 2367 2368 2369 static int hostapd_ctrl_rekey_ptk(struct hostapd_data *hapd, const char *cmd) 2370 { 2371 struct sta_info *sta; 2372 u8 addr[ETH_ALEN]; 2373 2374 if (hwaddr_aton(cmd, addr)) 2375 return -1; 2376 2377 sta = ap_get_sta(hapd, addr); 2378 if (!sta || !sta->wpa_sm) 2379 return -1; 2380 2381 return wpa_auth_rekey_ptk(hapd->wpa_auth, sta->wpa_sm); 2382 } 2383 2384 2385 static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr, 2386 char *buf, size_t buflen) 2387 { 2388 struct rsn_pmksa_cache_entry *pmksa; 2389 2390 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL); 2391 if (!pmksa) 2392 return -1; 2393 2394 return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len); 2395 } 2396 2397 2398 static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, 2399 char *buf, size_t buflen) 2400 { 2401 struct sta_info *sta; 2402 u8 addr[ETH_ALEN]; 2403 const u8 *pmk; 2404 int pmk_len; 2405 2406 if (hwaddr_aton(cmd, addr)) 2407 return -1; 2408 2409 sta = ap_get_sta(hapd, addr); 2410 if (!sta || !sta->wpa_sm) { 2411 wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR, 2412 MAC2STR(addr)); 2413 return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); 2414 } 2415 pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); 2416 if (!pmk || !pmk_len) { 2417 wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR, 2418 MAC2STR(addr)); 2419 return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); 2420 } 2421 2422 return wpa_snprintf_hex(buf, buflen, pmk, pmk_len); 2423 } 2424 2425 2426 static int hostapd_ctrl_register_frame(struct hostapd_data *hapd, 2427 const char *cmd) 2428 { 2429 u16 type; 2430 char *pos, *end; 2431 u8 match[10]; 2432 size_t match_len; 2433 bool multicast = false; 2434 2435 type = strtol(cmd, &pos, 16); 2436 if (*pos != ' ') 2437 return -1; 2438 pos++; 2439 end = os_strchr(pos, ' '); 2440 if (end) { 2441 match_len = end - pos; 2442 multicast = os_strstr(end, "multicast") != NULL; 2443 } else { 2444 match_len = os_strlen(pos) / 2; 2445 } 2446 if (hexstr2bin(pos, match, match_len)) 2447 return -1; 2448 2449 return hostapd_drv_register_frame(hapd, type, match, match_len, 2450 multicast); 2451 } 2452 2453 #endif /* CONFIG_TESTING_OPTIONS */ 2454 2455 2456 #ifdef NEED_AP_MLME 2457 static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params, 2458 u16 punct_bitmap) 2459 { 2460 u32 start_freq; 2461 2462 if (is_6ghz_freq(params->freq)) { 2463 const int bw_idx[] = { 20, 40, 80, 160, 320 }; 2464 int idx, bw; 2465 2466 /* The 6 GHz band requires HE to be enabled. */ 2467 params->he_enabled = 1; 2468 2469 if (params->center_freq1) { 2470 if (params->freq == 5935) 2471 idx = (params->center_freq1 - 5925) / 5; 2472 else 2473 idx = (params->center_freq1 - 5950) / 5; 2474 2475 bw = center_idx_to_bw_6ghz(idx); 2476 if (bw < 0 || bw > (int) ARRAY_SIZE(bw_idx) || 2477 bw_idx[bw] != params->bandwidth) 2478 return -1; 2479 } 2480 } else { /* Non-6 GHz channel */ 2481 /* An EHT STA is also an HE STA as defined in 2482 * IEEE P802.11be/D5.0, 4.3.16a. */ 2483 if (params->he_enabled || params->eht_enabled) { 2484 params->he_enabled = 1; 2485 /* An HE STA is also a VHT STA if operating in the 5 GHz 2486 * band and an HE STA is also an HT STA in the 2.4 GHz 2487 * band as defined in IEEE Std 802.11ax-2021, 4.3.15a. 2488 * A VHT STA is an HT STA as defined in IEEE 2489 * Std 802.11, 4.3.15. */ 2490 if (IS_5GHZ(params->freq)) 2491 params->vht_enabled = 1; 2492 2493 params->ht_enabled = 1; 2494 } 2495 } 2496 2497 switch (params->bandwidth) { 2498 case 0: 2499 /* bandwidth not specified: use 20 MHz by default */ 2500 /* fall-through */ 2501 case 20: 2502 if (params->center_freq1 && 2503 params->center_freq1 != params->freq) 2504 return -1; 2505 2506 if (params->center_freq2 || params->sec_channel_offset) 2507 return -1; 2508 2509 if (punct_bitmap) 2510 return -1; 2511 break; 2512 case 40: 2513 if (params->center_freq2 || !params->sec_channel_offset) 2514 return -1; 2515 2516 if (punct_bitmap) 2517 return -1; 2518 2519 if (!params->center_freq1) 2520 break; 2521 switch (params->sec_channel_offset) { 2522 case 1: 2523 if (params->freq + 10 != params->center_freq1) 2524 return -1; 2525 break; 2526 case -1: 2527 if (params->freq - 10 != params->center_freq1) 2528 return -1; 2529 break; 2530 default: 2531 return -1; 2532 } 2533 break; 2534 case 80: 2535 if (!params->center_freq1 || !params->sec_channel_offset) 2536 return 1; 2537 2538 switch (params->sec_channel_offset) { 2539 case 1: 2540 if (params->freq - 10 != params->center_freq1 && 2541 params->freq + 30 != params->center_freq1) 2542 return 1; 2543 break; 2544 case -1: 2545 if (params->freq + 10 != params->center_freq1 && 2546 params->freq - 30 != params->center_freq1) 2547 return -1; 2548 break; 2549 default: 2550 return -1; 2551 } 2552 2553 if (params->center_freq2 && punct_bitmap) 2554 return -1; 2555 2556 /* Adjacent and overlapped are not allowed for 80+80 */ 2557 if (params->center_freq2 && 2558 params->center_freq1 - params->center_freq2 <= 80 && 2559 params->center_freq2 - params->center_freq1 <= 80) 2560 return 1; 2561 break; 2562 case 160: 2563 if (!params->center_freq1 || params->center_freq2 || 2564 !params->sec_channel_offset) 2565 return -1; 2566 2567 switch (params->sec_channel_offset) { 2568 case 1: 2569 if (params->freq + 70 != params->center_freq1 && 2570 params->freq + 30 != params->center_freq1 && 2571 params->freq - 10 != params->center_freq1 && 2572 params->freq - 50 != params->center_freq1) 2573 return -1; 2574 break; 2575 case -1: 2576 if (params->freq + 50 != params->center_freq1 && 2577 params->freq + 10 != params->center_freq1 && 2578 params->freq - 30 != params->center_freq1 && 2579 params->freq - 70 != params->center_freq1) 2580 return -1; 2581 break; 2582 default: 2583 return -1; 2584 } 2585 break; 2586 case 320: 2587 if (!params->center_freq1 || params->center_freq2 || 2588 !params->sec_channel_offset) 2589 return -1; 2590 2591 switch (params->sec_channel_offset) { 2592 case 1: 2593 if (params->freq + 150 != params->center_freq1 && 2594 params->freq + 110 != params->center_freq1 && 2595 params->freq + 70 != params->center_freq1 && 2596 params->freq + 30 != params->center_freq1 && 2597 params->freq - 10 != params->center_freq1 && 2598 params->freq - 50 != params->center_freq1 && 2599 params->freq - 90 != params->center_freq1 && 2600 params->freq - 130 != params->center_freq1) 2601 return -1; 2602 break; 2603 case -1: 2604 if (params->freq + 130 != params->center_freq1 && 2605 params->freq + 90 != params->center_freq1 && 2606 params->freq + 50 != params->center_freq1 && 2607 params->freq + 10 != params->center_freq1 && 2608 params->freq - 30 != params->center_freq1 && 2609 params->freq - 70 != params->center_freq1 && 2610 params->freq - 110 != params->center_freq1 && 2611 params->freq - 150 != params->center_freq1) 2612 return -1; 2613 break; 2614 } 2615 break; 2616 default: 2617 return -1; 2618 } 2619 2620 if (!punct_bitmap) 2621 return 0; 2622 2623 if (!params->eht_enabled) { 2624 wpa_printf(MSG_ERROR, 2625 "Preamble puncturing supported only in EHT"); 2626 return -1; 2627 } 2628 2629 if (params->freq >= 2412 && params->freq <= 2484) { 2630 wpa_printf(MSG_ERROR, 2631 "Preamble puncturing is not supported in 2.4 GHz"); 2632 return -1; 2633 } 2634 2635 start_freq = params->center_freq1 - (params->bandwidth / 2); 2636 if (!is_punct_bitmap_valid(params->bandwidth, 2637 (params->freq - start_freq) / 20, 2638 punct_bitmap)) { 2639 wpa_printf(MSG_ERROR, "Invalid preamble puncturing bitmap"); 2640 return -1; 2641 } 2642 2643 return 0; 2644 } 2645 #endif /* NEED_AP_MLME */ 2646 2647 2648 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 2649 char *pos) 2650 { 2651 #ifdef NEED_AP_MLME 2652 struct csa_settings settings; 2653 int ret; 2654 int dfs_range = 0; 2655 unsigned int i; 2656 int bandwidth; 2657 u8 chan; 2658 unsigned int num_err = 0; 2659 int err = 0; 2660 2661 ret = hostapd_parse_csa_settings(pos, &settings); 2662 if (ret) 2663 return ret; 2664 2665 settings.link_id = -1; 2666 #ifdef CONFIG_IEEE80211BE 2667 if (iface->num_bss && iface->bss[0]->conf->mld_ap) 2668 settings.link_id = iface->bss[0]->mld_link_id; 2669 #endif /* CONFIG_IEEE80211BE */ 2670 2671 ret = hostapd_ctrl_check_freq_params(&settings.freq_params, 2672 settings.punct_bitmap); 2673 if (ret) { 2674 wpa_printf(MSG_INFO, 2675 "chanswitch: invalid frequency settings provided"); 2676 return ret; 2677 } 2678 2679 switch (settings.freq_params.bandwidth) { 2680 case 40: 2681 bandwidth = CHAN_WIDTH_40; 2682 break; 2683 case 80: 2684 if (settings.freq_params.center_freq2) 2685 bandwidth = CHAN_WIDTH_80P80; 2686 else 2687 bandwidth = CHAN_WIDTH_80; 2688 break; 2689 case 160: 2690 bandwidth = CHAN_WIDTH_160; 2691 break; 2692 case 320: 2693 bandwidth = CHAN_WIDTH_320; 2694 break; 2695 default: 2696 bandwidth = CHAN_WIDTH_20; 2697 break; 2698 } 2699 2700 if (settings.freq_params.center_freq1) 2701 dfs_range += hostapd_is_dfs_overlap( 2702 iface, bandwidth, settings.freq_params.center_freq1); 2703 else 2704 dfs_range += hostapd_is_dfs_overlap( 2705 iface, bandwidth, settings.freq_params.freq); 2706 2707 if (settings.freq_params.center_freq2) 2708 dfs_range += hostapd_is_dfs_overlap( 2709 iface, bandwidth, settings.freq_params.center_freq2); 2710 2711 if (dfs_range) { 2712 ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan); 2713 if (ret == NUM_HOSTAPD_MODES) { 2714 wpa_printf(MSG_ERROR, 2715 "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)", 2716 settings.freq_params.freq, 2717 settings.freq_params.sec_channel_offset, 2718 settings.freq_params.bandwidth); 2719 return -1; 2720 } 2721 2722 settings.freq_params.channel = chan; 2723 2724 wpa_printf(MSG_DEBUG, 2725 "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)", 2726 settings.freq_params.channel, 2727 settings.freq_params.freq, 2728 settings.freq_params.sec_channel_offset, 2729 settings.freq_params.bandwidth, 2730 settings.freq_params.center_freq1); 2731 2732 /* Perform CAC and switch channel */ 2733 iface->is_ch_switch_dfs = true; 2734 hostapd_switch_channel_fallback(iface, &settings.freq_params); 2735 return 0; 2736 } 2737 2738 for (i = 0; i < iface->num_bss; i++) { 2739 2740 /* Save CHAN_SWITCH VHT, HE, and EHT config */ 2741 hostapd_chan_switch_config(iface->bss[i], 2742 &settings.freq_params); 2743 2744 err = hostapd_switch_channel(iface->bss[i], &settings); 2745 if (err) { 2746 ret = err; 2747 num_err++; 2748 } 2749 } 2750 2751 return (iface->num_bss == num_err) ? ret : 0; 2752 #else /* NEED_AP_MLME */ 2753 return -1; 2754 #endif /* NEED_AP_MLME */ 2755 } 2756 2757 2758 #ifdef CONFIG_IEEE80211AX 2759 static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface, 2760 const char *pos) 2761 { 2762 #ifdef NEED_AP_MLME 2763 struct cca_settings settings; 2764 struct hostapd_data *hapd = iface->bss[0]; 2765 int ret, color; 2766 unsigned int i; 2767 char *end; 2768 2769 os_memset(&settings, 0, sizeof(settings)); 2770 2771 color = strtol(pos, &end, 10); 2772 if (pos == end || color < 0 || color > 63) { 2773 wpa_printf(MSG_ERROR, "color_change: Invalid color provided"); 2774 return -1; 2775 } 2776 2777 /* Color value is expected to be [1-63]. If 0 comes, assumption is this 2778 * is to disable the color. In this case no need to do CCA, just 2779 * changing Beacon frames is sufficient. */ 2780 if (color == 0) { 2781 if (iface->conf->he_op.he_bss_color_disabled) { 2782 wpa_printf(MSG_ERROR, 2783 "color_change: Color is already disabled"); 2784 return -1; 2785 } 2786 2787 iface->conf->he_op.he_bss_color_disabled = 1; 2788 2789 for (i = 0; i < iface->num_bss; i++) 2790 ieee802_11_set_beacon(iface->bss[i]); 2791 2792 return 0; 2793 } 2794 2795 if (color == iface->conf->he_op.he_bss_color) { 2796 if (!iface->conf->he_op.he_bss_color_disabled) { 2797 wpa_printf(MSG_ERROR, 2798 "color_change: Provided color is already set"); 2799 return -1; 2800 } 2801 2802 iface->conf->he_op.he_bss_color_disabled = 0; 2803 2804 for (i = 0; i < iface->num_bss; i++) 2805 ieee802_11_set_beacon(iface->bss[i]); 2806 2807 return 0; 2808 } 2809 2810 if (hapd->cca_in_progress) { 2811 wpa_printf(MSG_ERROR, 2812 "color_change: CCA is already in progress"); 2813 return -1; 2814 } 2815 2816 iface->conf->he_op.he_bss_color_disabled = 0; 2817 2818 for (i = 0; i < iface->num_bss; i++) { 2819 struct hostapd_data *bss = iface->bss[i]; 2820 2821 hostapd_cleanup_cca_params(bss); 2822 2823 bss->cca_color = color; 2824 bss->cca_count = 10; 2825 2826 if (hostapd_fill_cca_settings(bss, &settings)) { 2827 wpa_printf(MSG_DEBUG, 2828 "color_change: Filling CCA settings failed for color: %d\n", 2829 color); 2830 hostapd_cleanup_cca_params(bss); 2831 continue; 2832 } 2833 2834 wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color); 2835 ret = hostapd_drv_switch_color(bss, &settings); 2836 if (ret) 2837 hostapd_cleanup_cca_params(bss); 2838 2839 free_beacon_data(&settings.beacon_cca); 2840 free_beacon_data(&settings.beacon_after); 2841 } 2842 2843 return 0; 2844 #else /* NEED_AP_MLME */ 2845 return -1; 2846 #endif /* NEED_AP_MLME */ 2847 } 2848 #endif /* CONFIG_IEEE80211AX */ 2849 2850 2851 static u8 hostapd_maxnss(struct hostapd_data *hapd, struct sta_info *sta) 2852 { 2853 u8 *mcs_set = NULL; 2854 u16 mcs_map; 2855 u8 ht_rx_nss = 0; 2856 u8 vht_rx_nss = 1; 2857 u8 mcs; 2858 bool ht_supported = false; 2859 bool vht_supported = false; 2860 int i; 2861 2862 if (sta->ht_capabilities && (sta->flags & WLAN_STA_HT)) { 2863 mcs_set = sta->ht_capabilities->supported_mcs_set; 2864 ht_supported = true; 2865 } 2866 2867 if (sta->vht_capabilities && (sta->flags & WLAN_STA_VHT)) { 2868 mcs_map = le_to_host16( 2869 sta->vht_capabilities->vht_supported_mcs_set.rx_map); 2870 vht_supported = true; 2871 } 2872 2873 if (ht_supported && mcs_set) { 2874 if (mcs_set[0]) 2875 ht_rx_nss++; 2876 if (mcs_set[1]) 2877 ht_rx_nss++; 2878 if (mcs_set[2]) 2879 ht_rx_nss++; 2880 if (mcs_set[3]) 2881 ht_rx_nss++; 2882 } 2883 if (vht_supported) { 2884 for (i = 7; i >= 0; i--) { 2885 mcs = (mcs_map >> (2 * i)) & 0x03; 2886 if (mcs != 0x03) { 2887 vht_rx_nss = i + 1; 2888 break; 2889 } 2890 } 2891 } 2892 2893 return ht_rx_nss > vht_rx_nss ? ht_rx_nss : vht_rx_nss; 2894 } 2895 2896 2897 static char hostapd_ctrl_iface_notify_cw_htaction(struct hostapd_data *hapd, 2898 const u8 *addr, u8 width) 2899 { 2900 u8 buf[3]; 2901 char ret; 2902 2903 width = width >= 1 ? 1 : 0; 2904 2905 buf[0] = WLAN_ACTION_HT; 2906 buf[1] = WLAN_HT_ACTION_NOTIFY_CHANWIDTH; 2907 buf[2] = width; 2908 2909 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 2910 buf, sizeof(buf)); 2911 if (ret) 2912 wpa_printf(MSG_DEBUG, 2913 "Failed to send Notify Channel Width frame to " 2914 MACSTR, MAC2STR(addr)); 2915 2916 return ret; 2917 } 2918 2919 2920 static char hostapd_ctrl_iface_notify_cw_vhtaction(struct hostapd_data *hapd, 2921 const u8 *addr, u8 width) 2922 { 2923 u8 buf[3]; 2924 char ret; 2925 2926 buf[0] = WLAN_ACTION_VHT; 2927 buf[1] = WLAN_VHT_ACTION_OPMODE_NOTIF; 2928 buf[2] = width; 2929 2930 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 2931 buf, sizeof(buf)); 2932 if (ret) 2933 wpa_printf(MSG_DEBUG, 2934 "Failed to send Opeating Mode Notification frame to " 2935 MACSTR, MAC2STR(addr)); 2936 2937 return ret; 2938 } 2939 2940 2941 static char hostapd_ctrl_iface_notify_cw_change(struct hostapd_data *hapd, 2942 const char *cmd) 2943 { 2944 u8 cw, operating_mode = 0, nss; 2945 struct sta_info *sta; 2946 enum hostapd_hw_mode hw_mode; 2947 2948 if (is_6ghz_freq(hapd->iface->freq)) { 2949 wpa_printf(MSG_ERROR, "20/40 BSS coex not supported in 6 GHz"); 2950 return -1; 2951 } 2952 2953 cw = atoi(cmd); 2954 hw_mode = hapd->iface->current_mode->mode; 2955 if ((hw_mode == HOSTAPD_MODE_IEEE80211G || 2956 hw_mode == HOSTAPD_MODE_IEEE80211B) && 2957 !(cw == 0 || cw == 1)) { 2958 wpa_printf(MSG_ERROR, 2959 "Channel width should be either 20 MHz or 40 MHz for 2.4 GHz band"); 2960 return -1; 2961 } 2962 2963 switch (cw) { 2964 case 0: 2965 operating_mode = 0; 2966 break; 2967 case 1: 2968 operating_mode = VHT_OPMODE_CHANNEL_40MHZ; 2969 break; 2970 case 2: 2971 operating_mode = VHT_OPMODE_CHANNEL_80MHZ; 2972 break; 2973 case 3: 2974 operating_mode = VHT_OPMODE_CHANNEL_160MHZ; 2975 break; 2976 default: 2977 wpa_printf(MSG_ERROR, "Channel width should be between 0 to 3"); 2978 return -1; 2979 } 2980 2981 for (sta = hapd->sta_list; sta; sta = sta->next) { 2982 if ((sta->flags & WLAN_STA_VHT) && sta->vht_capabilities) { 2983 nss = hostapd_maxnss(hapd, sta) - 1; 2984 hostapd_ctrl_iface_notify_cw_vhtaction(hapd, sta->addr, 2985 operating_mode | 2986 (u8) (nss << 4)); 2987 continue; 2988 } 2989 2990 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) == 2991 WLAN_STA_HT && sta->ht_capabilities) 2992 hostapd_ctrl_iface_notify_cw_htaction(hapd, sta->addr, 2993 cw); 2994 } 2995 2996 return 0; 2997 } 2998 2999 3000 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 3001 int reply_size, const char *param) 3002 { 3003 #ifdef RADIUS_SERVER 3004 if (os_strcmp(param, "radius_server") == 0) { 3005 return radius_server_get_mib(hapd->radius_srv, reply, 3006 reply_size); 3007 } 3008 #endif /* RADIUS_SERVER */ 3009 return -1; 3010 } 3011 3012 3013 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 3014 char *buf, size_t buflen) 3015 { 3016 int ret; 3017 char *pos, *temp = NULL; 3018 u8 *data = NULL; 3019 unsigned int vendor_id, subcmd; 3020 enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; 3021 struct wpabuf *reply; 3022 size_t data_len = 0; 3023 3024 /** 3025 * cmd: <vendor id> <subcommand id> [<hex formatted data>] 3026 * [nested=<0|1>] 3027 */ 3028 vendor_id = strtoul(cmd, &pos, 16); 3029 if (!isblank((unsigned char) *pos)) 3030 return -EINVAL; 3031 3032 subcmd = strtoul(pos, &pos, 10); 3033 3034 if (*pos != '\0') { 3035 if (!isblank((unsigned char) *pos++)) 3036 return -EINVAL; 3037 3038 temp = os_strchr(pos, ' '); 3039 data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); 3040 } 3041 3042 if (data_len) { 3043 data_len /= 2; 3044 data = os_malloc(data_len); 3045 if (!data) 3046 return -ENOBUFS; 3047 3048 if (hexstr2bin(pos, data, data_len)) { 3049 wpa_printf(MSG_DEBUG, 3050 "Vendor command: wrong parameter format"); 3051 os_free(data); 3052 return -EINVAL; 3053 } 3054 } 3055 3056 pos = os_strstr(cmd, "nested="); 3057 if (pos) 3058 nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : 3059 NESTED_ATTR_NOT_USED; 3060 3061 reply = wpabuf_alloc((buflen - 1) / 2); 3062 if (!reply) { 3063 os_free(data); 3064 return -ENOBUFS; 3065 } 3066 3067 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 3068 nested_attr_flag, reply); 3069 3070 if (ret == 0) 3071 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 3072 wpabuf_len(reply)); 3073 3074 wpabuf_free(reply); 3075 os_free(data); 3076 3077 return ret; 3078 } 3079 3080 3081 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd, 3082 const char *cmd) 3083 { 3084 u8 addr[ETH_ALEN]; 3085 struct sta_info *sta; 3086 3087 if (hwaddr_aton(cmd, addr)) 3088 return -1; 3089 3090 sta = ap_get_sta(hapd, addr); 3091 if (!sta || !sta->eapol_sm) 3092 return -1; 3093 3094 eapol_auth_reauthenticate(sta->eapol_sm); 3095 return 0; 3096 } 3097 3098 3099 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd) 3100 { 3101 u8 addr[ETH_ALEN]; 3102 struct sta_info *sta; 3103 char *pos = cmd, *param; 3104 3105 if (hwaddr_aton(pos, addr) || pos[17] != ' ') 3106 return -1; 3107 pos += 18; 3108 param = pos; 3109 pos = os_strchr(pos, ' '); 3110 if (!pos) 3111 return -1; 3112 *pos++ = '\0'; 3113 3114 sta = ap_get_sta(hapd, addr); 3115 if (!sta || !sta->eapol_sm) 3116 return -1; 3117 3118 return eapol_auth_set_conf(sta->eapol_sm, param, pos); 3119 } 3120 3121 3122 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd, 3123 char *buf, size_t buflen) 3124 { 3125 char *pos, *end, *stamp; 3126 int ret; 3127 3128 /* cmd: "LOG_LEVEL [<level>]" */ 3129 if (*cmd == '\0') { 3130 pos = buf; 3131 end = buf + buflen; 3132 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 3133 "Timestamp: %d\n", 3134 debug_level_str(wpa_debug_level), 3135 wpa_debug_timestamp); 3136 if (os_snprintf_error(end - pos, ret)) 3137 ret = 0; 3138 3139 return ret; 3140 } 3141 3142 while (*cmd == ' ') 3143 cmd++; 3144 3145 stamp = os_strchr(cmd, ' '); 3146 if (stamp) { 3147 *stamp++ = '\0'; 3148 while (*stamp == ' ') { 3149 stamp++; 3150 } 3151 } 3152 3153 if (os_strlen(cmd)) { 3154 int level = str_to_debug_level(cmd); 3155 if (level < 0) 3156 return -1; 3157 wpa_debug_level = level; 3158 } 3159 3160 if (stamp && os_strlen(stamp)) 3161 wpa_debug_timestamp = atoi(stamp); 3162 3163 os_memcpy(buf, "OK\n", 3); 3164 return 3; 3165 } 3166 3167 3168 #ifdef NEED_AP_MLME 3169 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd, 3170 char *buf, size_t buflen) 3171 { 3172 struct hostapd_iface *iface = hapd->iface; 3173 char *pos, *end; 3174 struct hostapd_sta_info *info; 3175 struct os_reltime now; 3176 3177 if (!iface->num_sta_seen) 3178 return 0; 3179 3180 sta_track_expire(iface, 0); 3181 3182 pos = buf; 3183 end = buf + buflen; 3184 3185 os_get_reltime(&now); 3186 dl_list_for_each_reverse(info, &iface->sta_seen, 3187 struct hostapd_sta_info, list) { 3188 struct os_reltime age; 3189 int ret; 3190 3191 os_reltime_sub(&now, &info->last_seen, &age); 3192 ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n", 3193 MAC2STR(info->addr), (unsigned int) age.sec, 3194 info->ssi_signal); 3195 if (os_snprintf_error(end - pos, ret)) 3196 break; 3197 pos += ret; 3198 } 3199 3200 return pos - buf; 3201 } 3202 #endif /* NEED_AP_MLME */ 3203 3204 3205 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd, 3206 const char *cmd) 3207 { 3208 u8 addr[ETH_ALEN]; 3209 3210 if (hwaddr_aton(cmd, addr)) { 3211 wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address"); 3212 return -1; 3213 } 3214 3215 return hostapd_send_lci_req(hapd, addr); 3216 } 3217 3218 3219 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd) 3220 { 3221 u8 addr[ETH_ALEN]; 3222 char *token, *context = NULL; 3223 int random_interval, min_ap; 3224 u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS]; 3225 unsigned int n_responders; 3226 3227 token = str_token(cmd, " ", &context); 3228 if (!token || hwaddr_aton(token, addr)) { 3229 wpa_printf(MSG_INFO, 3230 "CTRL: REQ_RANGE - Bad destination address"); 3231 return -1; 3232 } 3233 3234 token = str_token(cmd, " ", &context); 3235 if (!token) 3236 return -1; 3237 3238 random_interval = atoi(token); 3239 if (random_interval < 0 || random_interval > 0xffff) 3240 return -1; 3241 3242 token = str_token(cmd, " ", &context); 3243 if (!token) 3244 return -1; 3245 3246 min_ap = atoi(token); 3247 if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP) 3248 return -1; 3249 3250 n_responders = 0; 3251 while ((token = str_token(cmd, " ", &context))) { 3252 if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) { 3253 wpa_printf(MSG_INFO, 3254 "CTRL: REQ_RANGE: Too many responders"); 3255 return -1; 3256 } 3257 3258 if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) { 3259 wpa_printf(MSG_INFO, 3260 "CTRL: REQ_RANGE: Bad responder address"); 3261 return -1; 3262 } 3263 3264 n_responders++; 3265 } 3266 3267 if (!n_responders) { 3268 wpa_printf(MSG_INFO, 3269 "CTRL: REQ_RANGE - No FTM responder address"); 3270 return -1; 3271 } 3272 3273 return hostapd_send_range_req(hapd, addr, random_interval, min_ap, 3274 responders, n_responders); 3275 } 3276 3277 3278 static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd, 3279 const char *cmd, char *reply, 3280 size_t reply_size) 3281 { 3282 u8 addr[ETH_ALEN]; 3283 const char *pos; 3284 struct wpabuf *req; 3285 int ret; 3286 u8 req_mode = 0; 3287 3288 if (hwaddr_aton(cmd, addr)) 3289 return -1; 3290 pos = os_strchr(cmd, ' '); 3291 if (!pos) 3292 return -1; 3293 pos++; 3294 if (os_strncmp(pos, "req_mode=", 9) == 0) { 3295 int val = hex2byte(pos + 9); 3296 3297 if (val < 0) 3298 return -1; 3299 req_mode = val; 3300 pos += 11; 3301 pos = os_strchr(pos, ' '); 3302 if (!pos) 3303 return -1; 3304 pos++; 3305 } 3306 req = wpabuf_parse_bin(pos); 3307 if (!req) 3308 return -1; 3309 3310 ret = hostapd_send_beacon_req(hapd, addr, req_mode, req); 3311 wpabuf_free(req); 3312 if (ret >= 0) 3313 ret = os_snprintf(reply, reply_size, "%d", ret); 3314 return ret; 3315 } 3316 3317 3318 static int hostapd_ctrl_iface_req_link_measurement(struct hostapd_data *hapd, 3319 const char *cmd, char *reply, 3320 size_t reply_size) 3321 { 3322 u8 addr[ETH_ALEN]; 3323 int ret; 3324 3325 if (hwaddr_aton(cmd, addr)) { 3326 wpa_printf(MSG_ERROR, 3327 "CTRL: REQ_LINK_MEASUREMENT: Invalid MAC address"); 3328 return -1; 3329 } 3330 3331 ret = hostapd_send_link_measurement_req(hapd, addr); 3332 if (ret >= 0) 3333 ret = os_snprintf(reply, reply_size, "%d", ret); 3334 return ret; 3335 } 3336 3337 3338 static int hostapd_ctrl_iface_show_neighbor(struct hostapd_data *hapd, 3339 char *buf, size_t buflen) 3340 { 3341 if (!(hapd->conf->radio_measurements[0] & 3342 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { 3343 wpa_printf(MSG_ERROR, 3344 "CTRL: SHOW_NEIGHBOR: Neighbor report is not enabled"); 3345 return -1; 3346 } 3347 3348 return hostapd_neighbor_show(hapd, buf, buflen); 3349 } 3350 3351 3352 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf) 3353 { 3354 struct wpa_ssid_value ssid; 3355 u8 bssid[ETH_ALEN]; 3356 struct wpabuf *nr, *lci = NULL, *civic = NULL; 3357 int stationary = 0; 3358 int bss_parameters = 0; 3359 char *tmp; 3360 int ret = -1; 3361 3362 if (!(hapd->conf->radio_measurements[0] & 3363 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { 3364 wpa_printf(MSG_ERROR, 3365 "CTRL: SET_NEIGHBOR: Neighbor report is not enabled"); 3366 return -1; 3367 } 3368 3369 if (hwaddr_aton(buf, bssid)) { 3370 wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID"); 3371 return -1; 3372 } 3373 3374 tmp = os_strstr(buf, "ssid="); 3375 if (!tmp || ssid_parse(tmp + 5, &ssid)) { 3376 wpa_printf(MSG_ERROR, 3377 "CTRL: SET_NEIGHBOR: Bad or missing SSID"); 3378 return -1; 3379 } 3380 buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' '); 3381 if (!buf) 3382 return -1; 3383 3384 tmp = os_strstr(buf, "nr="); 3385 if (!tmp) { 3386 wpa_printf(MSG_ERROR, 3387 "CTRL: SET_NEIGHBOR: Missing Neighbor Report element"); 3388 return -1; 3389 } 3390 3391 buf = os_strchr(tmp, ' '); 3392 if (buf) 3393 *buf++ = '\0'; 3394 3395 nr = wpabuf_parse_bin(tmp + 3); 3396 if (!nr) { 3397 wpa_printf(MSG_ERROR, 3398 "CTRL: SET_NEIGHBOR: Bad Neighbor Report element"); 3399 return -1; 3400 } 3401 3402 if (!buf) 3403 goto set; 3404 3405 tmp = os_strstr(buf, "lci="); 3406 if (tmp) { 3407 buf = os_strchr(tmp, ' '); 3408 if (buf) 3409 *buf++ = '\0'; 3410 lci = wpabuf_parse_bin(tmp + 4); 3411 if (!lci) { 3412 wpa_printf(MSG_ERROR, 3413 "CTRL: SET_NEIGHBOR: Bad LCI subelement"); 3414 goto fail; 3415 } 3416 } 3417 3418 if (!buf) 3419 goto set; 3420 3421 tmp = os_strstr(buf, "civic="); 3422 if (tmp) { 3423 buf = os_strchr(tmp, ' '); 3424 if (buf) 3425 *buf++ = '\0'; 3426 civic = wpabuf_parse_bin(tmp + 6); 3427 if (!civic) { 3428 wpa_printf(MSG_ERROR, 3429 "CTRL: SET_NEIGHBOR: Bad civic subelement"); 3430 goto fail; 3431 } 3432 } 3433 3434 if (!buf) 3435 goto set; 3436 3437 if (os_strstr(buf, "stat")) 3438 stationary = 1; 3439 3440 tmp = os_strstr(buf, "bss_parameter="); 3441 if (tmp) { 3442 bss_parameters = atoi(tmp + 14); 3443 if (bss_parameters < 0 || bss_parameters > 0xff) { 3444 wpa_printf(MSG_ERROR, 3445 "CTRL: SET_NEIGHBOR: Bad bss_parameters subelement"); 3446 goto fail; 3447 } 3448 } 3449 3450 set: 3451 ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic, 3452 stationary, bss_parameters); 3453 3454 fail: 3455 wpabuf_free(nr); 3456 wpabuf_free(lci); 3457 wpabuf_free(civic); 3458 3459 return ret; 3460 } 3461 3462 3463 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, 3464 char *buf) 3465 { 3466 struct wpa_ssid_value ssid; 3467 struct wpa_ssid_value *ssidp = NULL; 3468 u8 bssid[ETH_ALEN]; 3469 char *tmp; 3470 3471 if (hwaddr_aton(buf, bssid)) { 3472 wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID"); 3473 return -1; 3474 } 3475 3476 tmp = os_strstr(buf, "ssid="); 3477 if (tmp) { 3478 ssidp = &ssid; 3479 if (ssid_parse(tmp + 5, &ssid)) { 3480 wpa_printf(MSG_ERROR, 3481 "CTRL: REMOVE_NEIGHBOR: Bad SSID"); 3482 return -1; 3483 } 3484 } 3485 3486 return hostapd_neighbor_remove(hapd, bssid, ssidp); 3487 } 3488 3489 3490 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, 3491 size_t buflen) 3492 { 3493 int ret, i; 3494 char *pos, *end; 3495 3496 ret = os_snprintf(buf, buflen, "%016llX:\n", 3497 (long long unsigned) iface->drv_flags); 3498 if (os_snprintf_error(buflen, ret)) 3499 return -1; 3500 3501 pos = buf + ret; 3502 end = buf + buflen; 3503 3504 for (i = 0; i < 64; i++) { 3505 if (iface->drv_flags & (1LLU << i)) { 3506 ret = os_snprintf(pos, end - pos, "%s\n", 3507 driver_flag_to_string(1LLU << i)); 3508 if (os_snprintf_error(end - pos, ret)) 3509 return -1; 3510 pos += ret; 3511 } 3512 } 3513 3514 return pos - buf; 3515 } 3516 3517 3518 static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf, 3519 size_t buflen) 3520 { 3521 int ret, i; 3522 char *pos, *end; 3523 3524 ret = os_snprintf(buf, buflen, "%016llX:\n", 3525 (long long unsigned) iface->drv_flags2); 3526 if (os_snprintf_error(buflen, ret)) 3527 return -1; 3528 3529 pos = buf + ret; 3530 end = buf + buflen; 3531 3532 for (i = 0; i < 64; i++) { 3533 if (iface->drv_flags2 & (1LLU << i)) { 3534 ret = os_snprintf(pos, end - pos, "%s\n", 3535 driver_flag2_to_string(1LLU << i)); 3536 if (os_snprintf_error(end - pos, ret)) 3537 return -1; 3538 pos += ret; 3539 } 3540 } 3541 3542 return pos - buf; 3543 } 3544 3545 3546 static int hostapd_ctrl_iface_get_capability(struct hostapd_data *hapd, 3547 const char *field, char *buf, 3548 size_t buflen) 3549 { 3550 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field); 3551 3552 #ifdef CONFIG_DPP 3553 if (os_strcmp(field, "dpp") == 0) { 3554 int res; 3555 3556 #ifdef CONFIG_DPP3 3557 res = os_snprintf(buf, buflen, "DPP=3"); 3558 #elif defined(CONFIG_DPP2) 3559 res = os_snprintf(buf, buflen, "DPP=2"); 3560 #else /* CONFIG_DPP2 */ 3561 res = os_snprintf(buf, buflen, "DPP=1"); 3562 #endif /* CONFIG_DPP2 */ 3563 if (os_snprintf_error(buflen, res)) 3564 return -1; 3565 return res; 3566 } 3567 #endif /* CONFIG_DPP */ 3568 3569 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", 3570 field); 3571 3572 return -1; 3573 } 3574 3575 3576 #ifdef ANDROID 3577 static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd, 3578 char *buf, size_t buflen) 3579 { 3580 int ret; 3581 3582 ret = hostapd_drv_driver_cmd(hapd, cmd, buf, buflen); 3583 if (ret == 0) { 3584 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 3585 if (os_snprintf_error(buflen, ret)) 3586 ret = -1; 3587 } 3588 return ret; 3589 } 3590 #endif /* ANDROID */ 3591 3592 3593 #ifdef CONFIG_IEEE80211BE 3594 3595 static int hostapd_ctrl_iface_enable_mld(struct hostapd_iface *iface) 3596 { 3597 unsigned int i; 3598 3599 if (!iface || !iface->bss[0]->conf->mld_ap) { 3600 wpa_printf(MSG_ERROR, 3601 "Trying to enable AP MLD on an interface that is not affiliated with an AP MLD"); 3602 return -1; 3603 } 3604 3605 for (i = 0; i < iface->interfaces->count; ++i) { 3606 struct hostapd_iface *h_iface = iface->interfaces->iface[i]; 3607 struct hostapd_data *h_hapd = h_iface->bss[0]; 3608 3609 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0])) 3610 continue; 3611 3612 if (hostapd_enable_iface(h_iface)) { 3613 wpa_printf(MSG_ERROR, "Enabling of AP MLD failed"); 3614 return -1; 3615 } 3616 } 3617 return 0; 3618 } 3619 3620 3621 static void hostapd_disable_iface_bss(struct hostapd_iface *iface) 3622 { 3623 unsigned int i; 3624 3625 for (i = 0; i < iface->num_bss; i++) 3626 hostapd_bss_deinit_no_free(iface->bss[i]); 3627 } 3628 3629 3630 static int hostapd_ctrl_iface_disable_mld(struct hostapd_iface *iface) 3631 { 3632 unsigned int i; 3633 3634 if (!iface || !iface->bss[0]->conf->mld_ap) { 3635 wpa_printf(MSG_ERROR, 3636 "Trying to disable AP MLD on an interface that is not affiliated with an AP MLD."); 3637 return -1; 3638 } 3639 3640 /* First, disable BSSs before stopping beaconing and doing driver 3641 * deinit so that the broadcast Deauthentication frames go out. */ 3642 3643 for (i = 0; i < iface->interfaces->count; ++i) { 3644 struct hostapd_iface *h_iface = iface->interfaces->iface[i]; 3645 struct hostapd_data *h_hapd = h_iface->bss[0]; 3646 3647 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0])) 3648 continue; 3649 3650 hostapd_disable_iface_bss(iface); 3651 } 3652 3653 /* Then, fully disable interfaces */ 3654 for (i = 0; i < iface->interfaces->count; ++i) { 3655 struct hostapd_iface *h_iface = iface->interfaces->iface[i]; 3656 struct hostapd_data *h_hapd = h_iface->bss[0]; 3657 3658 if (!hostapd_is_ml_partner(h_hapd, iface->bss[0])) 3659 continue; 3660 3661 if (hostapd_disable_iface(h_iface)) { 3662 wpa_printf(MSG_ERROR, "Disabling AP MLD failed"); 3663 return -1; 3664 } 3665 } 3666 3667 return 0; 3668 } 3669 3670 3671 #ifdef CONFIG_TESTING_OPTIONS 3672 static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd, 3673 char *buf, size_t buflen) 3674 { 3675 int ret; 3676 u32 count = atoi(cmd); 3677 3678 if (!count) 3679 count = 1; 3680 3681 ret = hostapd_link_remove(hapd, count); 3682 if (ret == 0) { 3683 ret = os_snprintf(buf, buflen, "%s\n", "OK"); 3684 if (os_snprintf_error(buflen, ret)) 3685 ret = -1; 3686 else 3687 ret = 0; 3688 } 3689 3690 return ret; 3691 } 3692 #endif /* CONFIG_TESTING_OPTIONS */ 3693 #endif /* CONFIG_IEEE80211BE */ 3694 3695 3696 #ifdef CONFIG_NAN_USD 3697 3698 static int hostapd_ctrl_nan_publish(struct hostapd_data *hapd, char *cmd, 3699 char *buf, size_t buflen) 3700 { 3701 char *token, *context = NULL; 3702 int publish_id; 3703 struct nan_publish_params params; 3704 const char *service_name = NULL; 3705 struct wpabuf *ssi = NULL; 3706 int ret = -1; 3707 enum nan_service_protocol_type srv_proto_type = 0; 3708 3709 os_memset(¶ms, 0, sizeof(params)); 3710 /* USD shall use both solicited and unsolicited transmissions */ 3711 params.unsolicited = true; 3712 params.solicited = true; 3713 /* USD shall require FSD without GAS */ 3714 params.fsd = true; 3715 3716 while ((token = str_token(cmd, " ", &context))) { 3717 if (os_strncmp(token, "service_name=", 13) == 0) { 3718 service_name = token + 13; 3719 continue; 3720 } 3721 3722 if (os_strncmp(token, "ttl=", 4) == 0) { 3723 params.ttl = atoi(token + 4); 3724 continue; 3725 } 3726 3727 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 3728 srv_proto_type = atoi(token + 15); 3729 continue; 3730 } 3731 3732 if (os_strncmp(token, "ssi=", 4) == 0) { 3733 if (ssi) 3734 goto fail; 3735 ssi = wpabuf_parse_bin(token + 4); 3736 if (!ssi) 3737 goto fail; 3738 continue; 3739 } 3740 3741 if (os_strcmp(token, "solicited=0") == 0) { 3742 params.solicited = false; 3743 continue; 3744 } 3745 3746 if (os_strcmp(token, "unsolicited=0") == 0) { 3747 params.unsolicited = false; 3748 continue; 3749 } 3750 3751 if (os_strcmp(token, "fsd=0") == 0) { 3752 params.fsd = false; 3753 continue; 3754 } 3755 3756 wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s", 3757 token); 3758 goto fail; 3759 } 3760 3761 publish_id = hostapd_nan_usd_publish(hapd, service_name, srv_proto_type, 3762 ssi, ¶ms); 3763 if (publish_id > 0) 3764 ret = os_snprintf(buf, buflen, "%d", publish_id); 3765 fail: 3766 wpabuf_free(ssi); 3767 return ret; 3768 } 3769 3770 3771 static int hostapd_ctrl_nan_cancel_publish(struct hostapd_data *hapd, 3772 char *cmd) 3773 { 3774 char *token, *context = NULL; 3775 int publish_id = 0; 3776 3777 while ((token = str_token(cmd, " ", &context))) { 3778 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 3779 continue; 3780 wpa_printf(MSG_INFO, 3781 "CTRL: Invalid NAN_CANCEL_PUBLISH parameter: %s", 3782 token); 3783 return -1; 3784 } 3785 3786 if (publish_id <= 0) { 3787 wpa_printf(MSG_INFO, 3788 "CTRL: Invalid or missing NAN_CANCEL_PUBLISH publish_id"); 3789 return -1; 3790 } 3791 3792 hostapd_nan_usd_cancel_publish(hapd, publish_id); 3793 return 0; 3794 } 3795 3796 3797 static int hostapd_ctrl_nan_update_publish(struct hostapd_data *hapd, 3798 char *cmd) 3799 { 3800 char *token, *context = NULL; 3801 int publish_id = 0; 3802 struct wpabuf *ssi = NULL; 3803 int ret = -1; 3804 3805 while ((token = str_token(cmd, " ", &context))) { 3806 if (sscanf(token, "publish_id=%i", &publish_id) == 1) 3807 continue; 3808 if (os_strncmp(token, "ssi=", 4) == 0) { 3809 if (ssi) 3810 goto fail; 3811 ssi = wpabuf_parse_bin(token + 4); 3812 if (!ssi) 3813 goto fail; 3814 continue; 3815 } 3816 wpa_printf(MSG_INFO, 3817 "CTRL: Invalid NAN_UPDATE_PUBLISH parameter: %s", 3818 token); 3819 goto fail; 3820 } 3821 3822 if (publish_id <= 0) { 3823 wpa_printf(MSG_INFO, 3824 "CTRL: Invalid or missing NAN_UPDATE_PUBLISH publish_id"); 3825 goto fail; 3826 } 3827 3828 ret = hostapd_nan_usd_update_publish(hapd, publish_id, ssi); 3829 fail: 3830 wpabuf_free(ssi); 3831 return ret; 3832 } 3833 3834 3835 static int hostapd_ctrl_nan_subscribe(struct hostapd_data *hapd, char *cmd, 3836 char *buf, size_t buflen) 3837 { 3838 char *token, *context = NULL; 3839 int subscribe_id; 3840 struct nan_subscribe_params params; 3841 const char *service_name = NULL; 3842 struct wpabuf *ssi = NULL; 3843 int ret = -1; 3844 enum nan_service_protocol_type srv_proto_type = 0; 3845 3846 os_memset(¶ms, 0, sizeof(params)); 3847 3848 while ((token = str_token(cmd, " ", &context))) { 3849 if (os_strncmp(token, "service_name=", 13) == 0) { 3850 service_name = token + 13; 3851 continue; 3852 } 3853 3854 if (os_strcmp(token, "active=1") == 0) { 3855 params.active = true; 3856 continue; 3857 } 3858 3859 if (os_strncmp(token, "ttl=", 4) == 0) { 3860 params.ttl = atoi(token + 4); 3861 continue; 3862 } 3863 3864 if (os_strncmp(token, "srv_proto_type=", 15) == 0) { 3865 srv_proto_type = atoi(token + 15); 3866 continue; 3867 } 3868 3869 if (os_strncmp(token, "ssi=", 4) == 0) { 3870 if (ssi) 3871 goto fail; 3872 ssi = wpabuf_parse_bin(token + 4); 3873 if (!ssi) 3874 goto fail; 3875 continue; 3876 } 3877 3878 wpa_printf(MSG_INFO, 3879 "CTRL: Invalid NAN_SUBSCRIBE parameter: %s", 3880 token); 3881 goto fail; 3882 } 3883 3884 subscribe_id = hostapd_nan_usd_subscribe(hapd, service_name, 3885 srv_proto_type, ssi, 3886 ¶ms); 3887 if (subscribe_id > 0) 3888 ret = os_snprintf(buf, buflen, "%d", subscribe_id); 3889 fail: 3890 wpabuf_free(ssi); 3891 return ret; 3892 } 3893 3894 3895 static int hostapd_ctrl_nan_cancel_subscribe(struct hostapd_data *hapd, 3896 char *cmd) 3897 { 3898 char *token, *context = NULL; 3899 int subscribe_id = 0; 3900 3901 while ((token = str_token(cmd, " ", &context))) { 3902 if (sscanf(token, "subscribe_id=%i", &subscribe_id) == 1) 3903 continue; 3904 wpa_printf(MSG_INFO, 3905 "CTRL: Invalid NAN_CANCEL_SUBSCRIBE parameter: %s", 3906 token); 3907 return -1; 3908 } 3909 3910 if (subscribe_id <= 0) { 3911 wpa_printf(MSG_INFO, 3912 "CTRL: Invalid or missing NAN_CANCEL_SUBSCRIBE subscribe_id"); 3913 return -1; 3914 } 3915 3916 hostapd_nan_usd_cancel_subscribe(hapd, subscribe_id); 3917 return 0; 3918 } 3919 3920 3921 static int hostapd_ctrl_nan_transmit(struct hostapd_data *hapd, char *cmd) 3922 { 3923 char *token, *context = NULL; 3924 int handle = 0; 3925 int req_instance_id = 0; 3926 struct wpabuf *ssi = NULL; 3927 u8 peer_addr[ETH_ALEN]; 3928 int ret = -1; 3929 3930 os_memset(peer_addr, 0, ETH_ALEN); 3931 3932 while ((token = str_token(cmd, " ", &context))) { 3933 if (sscanf(token, "handle=%i", &handle) == 1) 3934 continue; 3935 3936 if (sscanf(token, "req_instance_id=%i", &req_instance_id) == 1) 3937 continue; 3938 3939 if (os_strncmp(token, "address=", 8) == 0) { 3940 if (hwaddr_aton(token + 8, peer_addr) < 0) 3941 return -1; 3942 continue; 3943 } 3944 3945 if (os_strncmp(token, "ssi=", 4) == 0) { 3946 if (ssi) 3947 goto fail; 3948 ssi = wpabuf_parse_bin(token + 4); 3949 if (!ssi) 3950 goto fail; 3951 continue; 3952 } 3953 3954 wpa_printf(MSG_INFO, 3955 "CTRL: Invalid NAN_TRANSMIT parameter: %s", 3956 token); 3957 goto fail; 3958 } 3959 3960 if (handle <= 0) { 3961 wpa_printf(MSG_INFO, 3962 "CTRL: Invalid or missing NAN_TRANSMIT handle"); 3963 goto fail; 3964 } 3965 3966 if (is_zero_ether_addr(peer_addr)) { 3967 wpa_printf(MSG_INFO, 3968 "CTRL: Invalid or missing NAN_TRANSMIT address"); 3969 goto fail; 3970 } 3971 3972 ret = hostapd_nan_usd_transmit(hapd, handle, ssi, NULL, peer_addr, 3973 req_instance_id); 3974 fail: 3975 wpabuf_free(ssi); 3976 return ret; 3977 } 3978 3979 #endif /* CONFIG_NAN_USD */ 3980 3981 3982 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, 3983 char *buf, char *reply, 3984 int reply_size, 3985 struct sockaddr_storage *from, 3986 socklen_t fromlen) 3987 { 3988 int reply_len, res; 3989 3990 os_memcpy(reply, "OK\n", 3); 3991 reply_len = 3; 3992 3993 if (os_strcmp(buf, "PING") == 0) { 3994 os_memcpy(reply, "PONG\n", 5); 3995 reply_len = 5; 3996 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 3997 if (wpa_debug_reopen_file() < 0) 3998 reply_len = -1; 3999 } else if (os_strcmp(buf, "CLOSE_LOG") == 0) { 4000 wpa_debug_stop_log(); 4001 } else if (os_strncmp(buf, "NOTE ", 5) == 0) { 4002 wpa_printf(MSG_INFO, "NOTE: %s", buf + 5); 4003 } else if (os_strcmp(buf, "STATUS") == 0) { 4004 reply_len = hostapd_ctrl_iface_status(hapd, reply, 4005 reply_size); 4006 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 4007 reply_len = hostapd_drv_status(hapd, reply, reply_size); 4008 } else if (os_strcmp(buf, "MIB") == 0) { 4009 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 4010 if (reply_len >= 0) { 4011 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 4012 reply_size - reply_len); 4013 if (res < 0) 4014 reply_len = -1; 4015 else 4016 reply_len += res; 4017 } 4018 if (reply_len >= 0) { 4019 res = ieee802_1x_get_mib(hapd, reply + reply_len, 4020 reply_size - reply_len); 4021 if (res < 0) 4022 reply_len = -1; 4023 else 4024 reply_len += res; 4025 } 4026 #ifndef CONFIG_NO_RADIUS 4027 if (reply_len >= 0) { 4028 res = radius_client_get_mib(hapd->radius, 4029 reply + reply_len, 4030 reply_size - reply_len); 4031 if (res < 0) 4032 reply_len = -1; 4033 else 4034 reply_len += res; 4035 } 4036 #endif /* CONFIG_NO_RADIUS */ 4037 } else if (os_strncmp(buf, "MIB ", 4) == 0) { 4038 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 4039 buf + 4); 4040 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 4041 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 4042 reply_size); 4043 } else if (os_strncmp(buf, "STA ", 4) == 0) { 4044 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 4045 reply_size); 4046 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 4047 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 4048 reply_size); 4049 } else if (os_strcmp(buf, "ATTACH") == 0) { 4050 if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL)) 4051 reply_len = -1; 4052 } else if (os_strncmp(buf, "ATTACH ", 7) == 0) { 4053 if (hostapd_ctrl_iface_attach(hapd, from, fromlen, buf + 7)) 4054 reply_len = -1; 4055 } else if (os_strcmp(buf, "DETACH") == 0) { 4056 if (hostapd_ctrl_iface_detach(hapd, from, fromlen)) 4057 reply_len = -1; 4058 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 4059 if (hostapd_ctrl_iface_level(hapd, from, fromlen, 4060 buf + 6)) 4061 reply_len = -1; 4062 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 4063 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 4064 reply_len = -1; 4065 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 4066 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 4067 reply_len = -1; 4068 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 4069 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 4070 reply_len = -1; 4071 #ifdef CONFIG_TAXONOMY 4072 } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) { 4073 reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10, 4074 reply, reply_size); 4075 #endif /* CONFIG_TAXONOMY */ 4076 } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) { 4077 if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9)) 4078 reply_len = -1; 4079 } else if (os_strcmp(buf, "STOP_AP") == 0) { 4080 if (hostapd_ctrl_iface_stop_ap(hapd)) 4081 reply_len = -1; 4082 #ifdef NEED_AP_MLME 4083 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 4084 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 4085 reply_len = -1; 4086 #endif /* NEED_AP_MLME */ 4087 #ifdef CONFIG_WPS 4088 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 4089 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 4090 reply_len = -1; 4091 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 4092 reply_len = hostapd_ctrl_iface_wps_check_pin( 4093 hapd, buf + 14, reply, reply_size); 4094 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 4095 if (hostapd_wps_button_pushed(hapd, NULL)) 4096 reply_len = -1; 4097 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 4098 if (hostapd_wps_cancel(hapd)) 4099 reply_len = -1; 4100 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 4101 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 4102 reply, reply_size); 4103 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 4104 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 4105 reply_len = -1; 4106 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 4107 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 4108 reply_size); 4109 #ifdef CONFIG_WPS_NFC 4110 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 4111 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 4112 reply_len = -1; 4113 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 4114 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 4115 hapd, buf + 21, reply, reply_size); 4116 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 4117 reply_len = hostapd_ctrl_iface_wps_nfc_token( 4118 hapd, buf + 14, reply, reply_size); 4119 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 4120 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 4121 hapd, buf + 21, reply, reply_size); 4122 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 4123 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 4124 reply_len = -1; 4125 #endif /* CONFIG_WPS_NFC */ 4126 #endif /* CONFIG_WPS */ 4127 #ifdef CONFIG_INTERWORKING 4128 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 4129 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 4130 reply_len = -1; 4131 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 4132 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 4133 reply_len = -1; 4134 #endif /* CONFIG_INTERWORKING */ 4135 #ifdef CONFIG_HS20 4136 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 4137 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 4138 reply_len = -1; 4139 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 4140 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 4141 reply_len = -1; 4142 #endif /* CONFIG_HS20 */ 4143 #ifdef CONFIG_WNM_AP 4144 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 4145 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 4146 reply_len = -1; 4147 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 4148 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 4149 reply_len = -1; 4150 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 4151 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) 4152 reply_len = -1; 4153 } else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) { 4154 if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15)) 4155 reply_len = -1; 4156 #endif /* CONFIG_WNM_AP */ 4157 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 4158 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 4159 reply_size); 4160 } else if (os_strncmp(buf, "SET ", 4) == 0) { 4161 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 4162 reply_len = -1; 4163 } else if (os_strncmp(buf, "GET ", 4) == 0) { 4164 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 4165 reply_size); 4166 } else if (os_strcmp(buf, "ENABLE") == 0) { 4167 if (hostapd_ctrl_iface_enable(hapd->iface)) 4168 reply_len = -1; 4169 } else if (os_strcmp(buf, "RELOAD_WPA_PSK") == 0) { 4170 if (hostapd_ctrl_iface_reload_wpa_psk(hapd)) 4171 reply_len = -1; 4172 #ifdef CONFIG_IEEE80211R_AP 4173 } else if (os_strcmp(buf, "GET_RXKHS") == 0) { 4174 reply_len = hostapd_ctrl_iface_get_rxkhs(hapd, reply, 4175 reply_size); 4176 } else if (os_strcmp(buf, "RELOAD_RXKHS") == 0) { 4177 if (hostapd_ctrl_iface_reload_rxkhs(hapd)) 4178 reply_len = -1; 4179 #endif /* CONFIG_IEEE80211R_AP */ 4180 } else if (os_strcmp(buf, "RELOAD_BSS") == 0) { 4181 if (hostapd_ctrl_iface_reload_bss(hapd)) 4182 reply_len = -1; 4183 } else if (os_strcmp(buf, "RELOAD_CONFIG") == 0) { 4184 if (hostapd_reload_config(hapd->iface)) 4185 reply_len = -1; 4186 } else if (os_strcmp(buf, "RELOAD") == 0) { 4187 if (hostapd_ctrl_iface_reload(hapd->iface)) 4188 reply_len = -1; 4189 } else if (os_strcmp(buf, "DISABLE") == 0) { 4190 if (hostapd_ctrl_iface_disable(hapd->iface)) 4191 reply_len = -1; 4192 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 4193 if (ieee802_11_set_beacon(hapd)) 4194 reply_len = -1; 4195 #ifdef CONFIG_TESTING_OPTIONS 4196 } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 4197 if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 4198 reply_len = -1; 4199 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 4200 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 4201 reply_len = -1; 4202 } else if (os_strncmp(buf, "MGMT_TX_STATUS_PROCESS ", 23) == 0) { 4203 if (hostapd_ctrl_iface_mgmt_tx_status_process(hapd, 4204 buf + 23) < 0) 4205 reply_len = -1; 4206 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 4207 if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0) 4208 reply_len = -1; 4209 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 4210 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0) 4211 reply_len = -1; 4212 } else if (os_strncmp(buf, "EAPOL_TX ", 9) == 0) { 4213 if (hostapd_ctrl_iface_eapol_tx(hapd, buf + 9) < 0) 4214 reply_len = -1; 4215 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 4216 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0) 4217 reply_len = -1; 4218 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 4219 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0) 4220 reply_len = -1; 4221 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 4222 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0) 4223 reply_len = -1; 4224 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 4225 if (testing_set_fail_pattern(true, buf + 16) < 0) 4226 reply_len = -1; 4227 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 4228 reply_len = testing_get_fail_pattern(true, reply, reply_size); 4229 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 4230 if (testing_set_fail_pattern(false, buf + 10) < 0) 4231 reply_len = -1; 4232 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 4233 reply_len = testing_get_fail_pattern(false, reply, reply_size); 4234 } else if (os_strncmp(buf, "RESET_PN ", 9) == 0) { 4235 if (hostapd_ctrl_reset_pn(hapd, buf + 9) < 0) 4236 reply_len = -1; 4237 } else if (os_strncmp(buf, "SET_KEY ", 8) == 0) { 4238 if (hostapd_ctrl_set_key(hapd, buf + 8) < 0) 4239 reply_len = -1; 4240 } else if (os_strncmp(buf, "RESEND_M1 ", 10) == 0) { 4241 if (hostapd_ctrl_resend_m1(hapd, buf + 10) < 0) 4242 reply_len = -1; 4243 } else if (os_strncmp(buf, "RESEND_M3 ", 10) == 0) { 4244 if (hostapd_ctrl_resend_m3(hapd, buf + 10) < 0) 4245 reply_len = -1; 4246 } else if (os_strncmp(buf, "RESEND_GROUP_M1 ", 16) == 0) { 4247 if (hostapd_ctrl_resend_group_m1(hapd, buf + 16) < 0) 4248 reply_len = -1; 4249 } else if (os_strncmp(buf, "REKEY_PTK ", 10) == 0) { 4250 if (hostapd_ctrl_rekey_ptk(hapd, buf + 10) < 0) 4251 reply_len = -1; 4252 } else if (os_strcmp(buf, "REKEY_GTK") == 0) { 4253 if (wpa_auth_rekey_gtk(hapd->wpa_auth) < 0) 4254 reply_len = -1; 4255 } else if (os_strncmp(buf, "GET_PMK ", 8) == 0) { 4256 reply_len = hostapd_ctrl_get_pmk(hapd, buf + 8, reply, 4257 reply_size); 4258 } else if (os_strncmp(buf, "REGISTER_FRAME ", 15) == 0) { 4259 if (hostapd_ctrl_register_frame(hapd, buf + 16) < 0) 4260 reply_len = -1; 4261 #endif /* CONFIG_TESTING_OPTIONS */ 4262 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 4263 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 4264 reply_len = -1; 4265 #ifdef CONFIG_IEEE80211AX 4266 } else if (os_strncmp(buf, "COLOR_CHANGE ", 13) == 0) { 4267 if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 13)) 4268 reply_len = -1; 4269 #endif /* CONFIG_IEEE80211AX */ 4270 } else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) { 4271 if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17)) 4272 reply_len = -1; 4273 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 4274 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 4275 reply_size); 4276 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 4277 ieee802_1x_erp_flush(hapd); 4278 #ifdef RADIUS_SERVER 4279 radius_server_erp_flush(hapd->radius_srv); 4280 #endif /* RADIUS_SERVER */ 4281 } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) { 4282 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13)) 4283 reply_len = -1; 4284 } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) { 4285 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10)) 4286 reply_len = -1; 4287 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 4288 reply_len = hostapd_ctrl_iface_log_level( 4289 hapd, buf + 9, reply, reply_size); 4290 #ifdef NEED_AP_MLME 4291 } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) { 4292 reply_len = hostapd_ctrl_iface_track_sta_list( 4293 hapd, reply, reply_size); 4294 #endif /* NEED_AP_MLME */ 4295 } else if (os_strcmp(buf, "PMKSA") == 0) { 4296 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply, 4297 reply_size); 4298 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 4299 hostapd_ctrl_iface_pmksa_flush(hapd); 4300 } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { 4301 if (hostapd_ctrl_iface_pmksa_add(hapd, buf + 10) < 0) 4302 reply_len = -1; 4303 } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) { 4304 if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13)) 4305 reply_len = -1; 4306 } else if (os_strcmp(buf, "SHOW_NEIGHBOR") == 0) { 4307 reply_len = hostapd_ctrl_iface_show_neighbor(hapd, reply, 4308 reply_size); 4309 } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) { 4310 if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16)) 4311 reply_len = -1; 4312 } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) { 4313 if (hostapd_ctrl_iface_req_lci(hapd, buf + 8)) 4314 reply_len = -1; 4315 } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) { 4316 if (hostapd_ctrl_iface_req_range(hapd, buf + 10)) 4317 reply_len = -1; 4318 } else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) { 4319 reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11, 4320 reply, reply_size); 4321 } else if (os_strncmp(buf, "REQ_LINK_MEASUREMENT ", 21) == 0) { 4322 reply_len = hostapd_ctrl_iface_req_link_measurement( 4323 hapd, buf + 21, reply, reply_size); 4324 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 4325 reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, 4326 reply_size); 4327 } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { 4328 reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply, 4329 reply_size); 4330 } else if (os_strcmp(buf, "TERMINATE") == 0) { 4331 eloop_terminate(); 4332 } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { 4333 if (os_strncmp(buf + 11, "ADD_MAC ", 8) == 0) { 4334 if (hostapd_ctrl_iface_acl_add_mac( 4335 &hapd->conf->accept_mac, 4336 &hapd->conf->num_accept_mac, buf + 19) || 4337 hostapd_set_acl(hapd)) 4338 reply_len = -1; 4339 } else if (os_strncmp((buf + 11), "DEL_MAC ", 8) == 0) { 4340 if (hostapd_ctrl_iface_acl_del_mac( 4341 &hapd->conf->accept_mac, 4342 &hapd->conf->num_accept_mac, buf + 19) || 4343 hostapd_set_acl(hapd) || 4344 hostapd_disassoc_accept_mac(hapd)) 4345 reply_len = -1; 4346 } else if (os_strcmp(buf + 11, "SHOW") == 0) { 4347 reply_len = hostapd_ctrl_iface_acl_show_mac( 4348 hapd->conf->accept_mac, 4349 hapd->conf->num_accept_mac, reply, reply_size); 4350 } else if (os_strcmp(buf + 11, "CLEAR") == 0) { 4351 hostapd_ctrl_iface_acl_clear_list( 4352 &hapd->conf->accept_mac, 4353 &hapd->conf->num_accept_mac); 4354 if (hostapd_set_acl(hapd) || 4355 hostapd_disassoc_accept_mac(hapd)) 4356 reply_len = -1; 4357 } else { 4358 reply_len = -1; 4359 } 4360 } else if (os_strncmp(buf, "DENY_ACL ", 9) == 0) { 4361 if (os_strncmp(buf + 9, "ADD_MAC ", 8) == 0) { 4362 if (hostapd_ctrl_iface_acl_add_mac( 4363 &hapd->conf->deny_mac, 4364 &hapd->conf->num_deny_mac, buf + 17) || 4365 hostapd_set_acl(hapd) || 4366 hostapd_disassoc_deny_mac(hapd)) 4367 reply_len = -1; 4368 } else if (os_strncmp(buf + 9, "DEL_MAC ", 8) == 0) { 4369 if (hostapd_ctrl_iface_acl_del_mac( 4370 &hapd->conf->deny_mac, 4371 &hapd->conf->num_deny_mac, buf + 17) || 4372 hostapd_set_acl(hapd)) 4373 reply_len = -1; 4374 } else if (os_strcmp(buf + 9, "SHOW") == 0) { 4375 reply_len = hostapd_ctrl_iface_acl_show_mac( 4376 hapd->conf->deny_mac, 4377 hapd->conf->num_deny_mac, reply, reply_size); 4378 } else if (os_strcmp(buf + 9, "CLEAR") == 0) { 4379 hostapd_ctrl_iface_acl_clear_list( 4380 &hapd->conf->deny_mac, 4381 &hapd->conf->num_deny_mac); 4382 if (hostapd_set_acl(hapd)) 4383 reply_len = -1; 4384 } else { 4385 reply_len = -1; 4386 } 4387 #ifdef CONFIG_DPP 4388 } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { 4389 res = hostapd_dpp_qr_code(hapd, buf + 12); 4390 if (res < 0) { 4391 reply_len = -1; 4392 } else { 4393 reply_len = os_snprintf(reply, reply_size, "%d", res); 4394 if (os_snprintf_error(reply_size, reply_len)) 4395 reply_len = -1; 4396 } 4397 } else if (os_strncmp(buf, "DPP_NFC_URI ", 12) == 0) { 4398 res = hostapd_dpp_nfc_uri(hapd, buf + 12); 4399 if (res < 0) { 4400 reply_len = -1; 4401 } else { 4402 reply_len = os_snprintf(reply, reply_size, "%d", res); 4403 if (os_snprintf_error(reply_size, reply_len)) 4404 reply_len = -1; 4405 } 4406 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_REQ ", 21) == 0) { 4407 res = hostapd_dpp_nfc_handover_req(hapd, buf + 20); 4408 if (res < 0) { 4409 reply_len = -1; 4410 } else { 4411 reply_len = os_snprintf(reply, reply_size, "%d", res); 4412 if (os_snprintf_error(reply_size, reply_len)) 4413 reply_len = -1; 4414 } 4415 } else if (os_strncmp(buf, "DPP_NFC_HANDOVER_SEL ", 21) == 0) { 4416 res = hostapd_dpp_nfc_handover_sel(hapd, buf + 20); 4417 if (res < 0) { 4418 reply_len = -1; 4419 } else { 4420 reply_len = os_snprintf(reply, reply_size, "%d", res); 4421 if (os_snprintf_error(reply_size, reply_len)) 4422 reply_len = -1; 4423 } 4424 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { 4425 res = dpp_bootstrap_gen(hapd->iface->interfaces->dpp, buf + 18); 4426 if (res < 0) { 4427 reply_len = -1; 4428 } else { 4429 reply_len = os_snprintf(reply, reply_size, "%d", res); 4430 if (os_snprintf_error(reply_size, reply_len)) 4431 reply_len = -1; 4432 } 4433 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { 4434 if (dpp_bootstrap_remove(hapd->iface->interfaces->dpp, 4435 buf + 21) < 0) 4436 reply_len = -1; 4437 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { 4438 const char *uri; 4439 4440 uri = dpp_bootstrap_get_uri(hapd->iface->interfaces->dpp, 4441 atoi(buf + 22)); 4442 if (!uri) { 4443 reply_len = -1; 4444 } else { 4445 reply_len = os_snprintf(reply, reply_size, "%s", uri); 4446 if (os_snprintf_error(reply_size, reply_len)) 4447 reply_len = -1; 4448 } 4449 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { 4450 reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, 4451 atoi(buf + 19), 4452 reply, reply_size); 4453 } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { 4454 if (dpp_bootstrap_set(hapd->iface->interfaces->dpp, 4455 atoi(buf + 18), 4456 os_strchr(buf + 18, ' ')) < 0) 4457 reply_len = -1; 4458 } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { 4459 if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) 4460 reply_len = -1; 4461 } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { 4462 if (hostapd_dpp_listen(hapd, buf + 11) < 0) 4463 reply_len = -1; 4464 } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { 4465 hostapd_dpp_stop(hapd); 4466 hostapd_dpp_listen_stop(hapd); 4467 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { 4468 res = dpp_configurator_add(hapd->iface->interfaces->dpp, 4469 buf + 20); 4470 if (res < 0) { 4471 reply_len = -1; 4472 } else { 4473 reply_len = os_snprintf(reply, reply_size, "%d", res); 4474 if (os_snprintf_error(reply_size, reply_len)) 4475 reply_len = -1; 4476 } 4477 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SET ", 21) == 0) { 4478 if (dpp_configurator_set(hapd->iface->interfaces->dpp, 4479 buf + 20) < 0) 4480 reply_len = -1; 4481 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { 4482 if (dpp_configurator_remove(hapd->iface->interfaces->dpp, 4483 buf + 24) < 0) 4484 reply_len = -1; 4485 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { 4486 if (hostapd_dpp_configurator_sign(hapd, buf + 21) < 0) 4487 reply_len = -1; 4488 } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { 4489 reply_len = dpp_configurator_get_key_id( 4490 hapd->iface->interfaces->dpp, 4491 atoi(buf + 25), 4492 reply, reply_size); 4493 } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { 4494 res = hostapd_dpp_pkex_add(hapd, buf + 12); 4495 if (res < 0) { 4496 reply_len = -1; 4497 } else { 4498 reply_len = os_snprintf(reply, reply_size, "%d", res); 4499 if (os_snprintf_error(reply_size, reply_len)) 4500 reply_len = -1; 4501 } 4502 } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { 4503 if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) 4504 reply_len = -1; 4505 #ifdef CONFIG_DPP2 4506 } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { 4507 if (hostapd_dpp_controller_start(hapd, buf + 20) < 0) 4508 reply_len = -1; 4509 } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { 4510 if (hostapd_dpp_controller_start(hapd, NULL) < 0) 4511 reply_len = -1; 4512 } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { 4513 dpp_controller_stop(hapd->iface->interfaces->dpp); 4514 } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { 4515 if (hostapd_dpp_chirp(hapd, buf + 9) < 0) 4516 reply_len = -1; 4517 } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { 4518 hostapd_dpp_chirp_stop(hapd); 4519 } else if (os_strncmp(buf, "DPP_RELAY_ADD_CONTROLLER ", 25) == 0) { 4520 if (hostapd_dpp_add_controller(hapd, buf + 25) < 0) 4521 reply_len = -1; 4522 } else if (os_strncmp(buf, "DPP_RELAY_REMOVE_CONTROLLER ", 28) == 0) { 4523 hostapd_dpp_remove_controller(hapd, buf + 28); 4524 #endif /* CONFIG_DPP2 */ 4525 #ifdef CONFIG_DPP3 4526 } else if (os_strcmp(buf, "DPP_PUSH_BUTTON") == 0) { 4527 if (hostapd_dpp_push_button(hapd, NULL) < 0) 4528 reply_len = -1; 4529 } else if (os_strncmp(buf, "DPP_PUSH_BUTTON ", 16) == 0) { 4530 if (hostapd_dpp_push_button(hapd, buf + 15) < 0) 4531 reply_len = -1; 4532 #endif /* CONFIG_DPP3 */ 4533 #endif /* CONFIG_DPP */ 4534 #ifdef CONFIG_NAN_USD 4535 } else if (os_strncmp(buf, "NAN_PUBLISH ", 12) == 0) { 4536 reply_len = hostapd_ctrl_nan_publish(hapd, buf + 12, reply, 4537 reply_size); 4538 } else if (os_strncmp(buf, "NAN_CANCEL_PUBLISH ", 19) == 0) { 4539 if (hostapd_ctrl_nan_cancel_publish(hapd, buf + 19) < 0) 4540 reply_len = -1; 4541 } else if (os_strncmp(buf, "NAN_UPDATE_PUBLISH ", 19) == 0) { 4542 if (hostapd_ctrl_nan_update_publish(hapd, buf + 19) < 0) 4543 reply_len = -1; 4544 } else if (os_strncmp(buf, "NAN_SUBSCRIBE ", 14) == 0) { 4545 reply_len = hostapd_ctrl_nan_subscribe(hapd, buf + 14, reply, 4546 reply_size); 4547 } else if (os_strncmp(buf, "NAN_CANCEL_SUBSCRIBE ", 21) == 0) { 4548 if (hostapd_ctrl_nan_cancel_subscribe(hapd, buf + 21) < 0) 4549 reply_len = -1; 4550 } else if (os_strncmp(buf, "NAN_TRANSMIT ", 13) == 0) { 4551 if (hostapd_ctrl_nan_transmit(hapd, buf + 13) < 0) 4552 reply_len = -1; 4553 #endif /* CONFIG_NAN_USD */ 4554 #ifdef RADIUS_SERVER 4555 } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) { 4556 if (radius_server_dac_request(hapd->radius_srv, buf + 12) < 0) 4557 reply_len = -1; 4558 #endif /* RADIUS_SERVER */ 4559 } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { 4560 reply_len = hostapd_ctrl_iface_get_capability( 4561 hapd, buf + 15, reply, reply_size); 4562 #ifdef CONFIG_PASN 4563 } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) { 4564 reply_len = ptksa_cache_list(hapd->ptksa, reply, reply_size); 4565 #endif /* CONFIG_PASN */ 4566 #ifdef ANDROID 4567 } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { 4568 reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply, 4569 reply_size); 4570 #endif /* ANDROID */ 4571 #ifdef CONFIG_IEEE80211BE 4572 } else if (os_strcmp(buf, "ENABLE_MLD") == 0) { 4573 if (hostapd_ctrl_iface_enable_mld(hapd->iface)) 4574 reply_len = -1; 4575 } else if (os_strcmp(buf, "DISABLE_MLD") == 0) { 4576 if (hostapd_ctrl_iface_disable_mld(hapd->iface)) 4577 reply_len = -1; 4578 #ifdef CONFIG_TESTING_OPTIONS 4579 } else if (os_strncmp(buf, "LINK_REMOVE ", 12) == 0) { 4580 if (hostapd_ctrl_iface_link_remove(hapd, buf + 12, 4581 reply, reply_size)) 4582 reply_len = -1; 4583 #endif /* CONFIG_TESTING_OPTIONS */ 4584 #endif /* CONFIG_IEEE80211BE */ 4585 } else { 4586 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 4587 reply_len = 16; 4588 } 4589 4590 if (reply_len < 0) { 4591 os_memcpy(reply, "FAIL\n", 5); 4592 reply_len = 5; 4593 } 4594 4595 return reply_len; 4596 } 4597 4598 4599 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 4600 void *sock_ctx) 4601 { 4602 struct hostapd_data *hapd = eloop_ctx; 4603 char buf[4096]; 4604 int res; 4605 struct sockaddr_storage from; 4606 socklen_t fromlen = sizeof(from); 4607 char *reply, *pos = buf; 4608 const int reply_size = 4096; 4609 int reply_len; 4610 int level = MSG_DEBUG; 4611 #ifdef CONFIG_CTRL_IFACE_UDP 4612 unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; 4613 #endif /* CONFIG_CTRL_IFACE_UDP */ 4614 4615 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 4616 (struct sockaddr *) &from, &fromlen); 4617 if (res < 0) { 4618 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 4619 strerror(errno)); 4620 return; 4621 } 4622 buf[res] = '\0'; 4623 4624 reply = os_malloc(reply_size); 4625 if (reply == NULL) { 4626 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 4627 fromlen) < 0) { 4628 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 4629 strerror(errno)); 4630 } 4631 return; 4632 } 4633 4634 #ifdef CONFIG_CTRL_IFACE_UDP 4635 if (os_strcmp(buf, "GET_COOKIE") == 0) { 4636 os_memcpy(reply, "COOKIE=", 7); 4637 wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, 4638 hapd->ctrl_iface_cookie, 4639 CTRL_IFACE_COOKIE_LEN); 4640 reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; 4641 goto done; 4642 } 4643 4644 if (os_strncmp(buf, "COOKIE=", 7) != 0 || 4645 hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { 4646 wpa_printf(MSG_DEBUG, 4647 "CTRL: No cookie in the request - drop request"); 4648 os_free(reply); 4649 return; 4650 } 4651 4652 if (os_memcmp(hapd->ctrl_iface_cookie, lcookie, 4653 CTRL_IFACE_COOKIE_LEN) != 0) { 4654 wpa_printf(MSG_DEBUG, 4655 "CTRL: Invalid cookie in the request - drop request"); 4656 os_free(reply); 4657 return; 4658 } 4659 4660 pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN; 4661 while (*pos == ' ') 4662 pos++; 4663 #endif /* CONFIG_CTRL_IFACE_UDP */ 4664 4665 if (os_strcmp(pos, "PING") == 0) 4666 level = MSG_EXCESSIVE; 4667 wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res); 4668 4669 reply_len = hostapd_ctrl_iface_receive_process(hapd, pos, 4670 reply, reply_size, 4671 &from, fromlen); 4672 4673 #ifdef CONFIG_CTRL_IFACE_UDP 4674 done: 4675 #endif /* CONFIG_CTRL_IFACE_UDP */ 4676 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 4677 fromlen) < 0) { 4678 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 4679 strerror(errno)); 4680 } 4681 os_free(reply); 4682 } 4683 4684 4685 #ifndef CONFIG_CTRL_IFACE_UDP 4686 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 4687 { 4688 char *buf; 4689 size_t len; 4690 4691 if (hapd->conf->ctrl_interface == NULL) 4692 return NULL; 4693 4694 len = os_strlen(hapd->conf->ctrl_interface) + 4695 os_strlen(hapd->conf->iface) + 2; 4696 buf = os_malloc(len); 4697 if (buf == NULL) 4698 return NULL; 4699 4700 os_snprintf(buf, len, "%s/%s", 4701 hapd->conf->ctrl_interface, hapd->conf->iface); 4702 buf[len - 1] = '\0'; 4703 return buf; 4704 } 4705 #endif /* CONFIG_CTRL_IFACE_UDP */ 4706 4707 4708 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 4709 enum wpa_msg_type type, 4710 const char *txt, size_t len) 4711 { 4712 struct hostapd_data *hapd = ctx; 4713 if (hapd == NULL) 4714 return; 4715 hostapd_ctrl_iface_send(hapd, level, type, txt, len); 4716 } 4717 4718 4719 int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 4720 { 4721 #ifdef CONFIG_CTRL_IFACE_UDP 4722 int port = HOSTAPD_CTRL_IFACE_PORT; 4723 char p[32] = { 0 }; 4724 char port_str[40], *tmp; 4725 char *pos; 4726 struct addrinfo hints = { 0 }, *res, *saveres; 4727 int n; 4728 4729 if (hapd->ctrl_sock > -1) { 4730 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 4731 return 0; 4732 } 4733 4734 if (hapd->conf->ctrl_interface == NULL) 4735 return 0; 4736 4737 pos = os_strstr(hapd->conf->ctrl_interface, "udp:"); 4738 if (pos) { 4739 pos += 4; 4740 port = atoi(pos); 4741 if (port <= 0) { 4742 wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port"); 4743 goto fail; 4744 } 4745 } 4746 4747 dl_list_init(&hapd->ctrl_dst); 4748 hapd->ctrl_sock = -1; 4749 os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); 4750 4751 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 4752 hints.ai_flags = AI_PASSIVE; 4753 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 4754 4755 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 4756 hints.ai_family = AF_INET6; 4757 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4758 hints.ai_family = AF_INET; 4759 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 4760 hints.ai_socktype = SOCK_DGRAM; 4761 4762 try_again: 4763 os_snprintf(p, sizeof(p), "%d", port); 4764 n = getaddrinfo(NULL, p, &hints, &res); 4765 if (n) { 4766 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 4767 goto fail; 4768 } 4769 4770 saveres = res; 4771 hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype, 4772 res->ai_protocol); 4773 if (hapd->ctrl_sock < 0) { 4774 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 4775 goto fail; 4776 } 4777 4778 if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) { 4779 port--; 4780 if ((HOSTAPD_CTRL_IFACE_PORT - port) < 4781 HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos) 4782 goto try_again; 4783 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 4784 goto fail; 4785 } 4786 4787 freeaddrinfo(saveres); 4788 4789 os_snprintf(port_str, sizeof(port_str), "udp:%d", port); 4790 tmp = os_strdup(port_str); 4791 if (tmp) { 4792 os_free(hapd->conf->ctrl_interface); 4793 hapd->conf->ctrl_interface = tmp; 4794 } 4795 wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 4796 4797 if (eloop_register_read_sock(hapd->ctrl_sock, 4798 hostapd_ctrl_iface_receive, hapd, NULL) < 4799 0) { 4800 hostapd_ctrl_iface_deinit(hapd); 4801 return -1; 4802 } 4803 4804 hapd->msg_ctx = hapd; 4805 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 4806 4807 return 0; 4808 4809 fail: 4810 if (hapd->ctrl_sock >= 0) 4811 close(hapd->ctrl_sock); 4812 return -1; 4813 #else /* CONFIG_CTRL_IFACE_UDP */ 4814 struct sockaddr_un addr; 4815 int s = -1; 4816 char *fname = NULL; 4817 4818 if (hapd->ctrl_sock > -1) { 4819 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 4820 return 0; 4821 } 4822 4823 dl_list_init(&hapd->ctrl_dst); 4824 4825 if (hapd->conf->ctrl_interface == NULL) 4826 return 0; 4827 4828 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 4829 if (errno == EEXIST) { 4830 wpa_printf(MSG_DEBUG, "Using existing control " 4831 "interface directory."); 4832 } else { 4833 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 4834 strerror(errno)); 4835 goto fail; 4836 } 4837 } 4838 4839 if (hapd->conf->ctrl_interface_gid_set && 4840 lchown(hapd->conf->ctrl_interface, -1, 4841 hapd->conf->ctrl_interface_gid) < 0) { 4842 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 4843 strerror(errno)); 4844 return -1; 4845 } 4846 4847 if (!hapd->conf->ctrl_interface_gid_set && 4848 hapd->iface->interfaces->ctrl_iface_group && 4849 lchown(hapd->conf->ctrl_interface, -1, 4850 hapd->iface->interfaces->ctrl_iface_group) < 0) { 4851 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 4852 strerror(errno)); 4853 return -1; 4854 } 4855 4856 #ifdef ANDROID 4857 /* 4858 * Android is using umask 0077 which would leave the control interface 4859 * directory without group access. This breaks things since Wi-Fi 4860 * framework assumes that this directory can be accessed by other 4861 * applications in the wifi group. Fix this by adding group access even 4862 * if umask value would prevent this. 4863 */ 4864 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 4865 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 4866 strerror(errno)); 4867 /* Try to continue anyway */ 4868 } 4869 #endif /* ANDROID */ 4870 4871 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 4872 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 4873 goto fail; 4874 4875 s = socket(PF_UNIX, SOCK_DGRAM, 0); 4876 if (s < 0) { 4877 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 4878 goto fail; 4879 } 4880 4881 os_memset(&addr, 0, sizeof(addr)); 4882 #ifdef __FreeBSD__ 4883 addr.sun_len = sizeof(addr); 4884 #endif /* __FreeBSD__ */ 4885 addr.sun_family = AF_UNIX; 4886 fname = hostapd_ctrl_iface_path(hapd); 4887 if (fname == NULL) 4888 goto fail; 4889 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 4890 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 4891 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 4892 strerror(errno)); 4893 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 4894 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 4895 " allow connections - assuming it was left" 4896 "over from forced program termination"); 4897 if (unlink(fname) < 0) { 4898 wpa_printf(MSG_ERROR, 4899 "Could not unlink existing ctrl_iface socket '%s': %s", 4900 fname, strerror(errno)); 4901 goto fail; 4902 } 4903 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 4904 0) { 4905 wpa_printf(MSG_ERROR, 4906 "hostapd-ctrl-iface: bind(PF_UNIX): %s", 4907 strerror(errno)); 4908 goto fail; 4909 } 4910 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 4911 "ctrl_iface socket '%s'", fname); 4912 } else { 4913 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 4914 "be in use - cannot override it"); 4915 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 4916 "not used anymore", fname); 4917 os_free(fname); 4918 fname = NULL; 4919 goto fail; 4920 } 4921 } 4922 4923 if (hapd->conf->ctrl_interface_gid_set && 4924 lchown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 4925 wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", 4926 strerror(errno)); 4927 goto fail; 4928 } 4929 4930 if (!hapd->conf->ctrl_interface_gid_set && 4931 hapd->iface->interfaces->ctrl_iface_group && 4932 lchown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 4933 wpa_printf(MSG_ERROR, "lchown[ctrl_interface/ifname]: %s", 4934 strerror(errno)); 4935 goto fail; 4936 } 4937 4938 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 4939 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 4940 strerror(errno)); 4941 goto fail; 4942 } 4943 os_free(fname); 4944 4945 hapd->ctrl_sock = s; 4946 if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 4947 NULL) < 0) { 4948 hostapd_ctrl_iface_deinit(hapd); 4949 return -1; 4950 } 4951 hapd->msg_ctx = hapd; 4952 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 4953 4954 return 0; 4955 4956 fail: 4957 if (s >= 0) 4958 close(s); 4959 if (fname) { 4960 unlink(fname); 4961 os_free(fname); 4962 } 4963 return -1; 4964 #endif /* CONFIG_CTRL_IFACE_UDP */ 4965 } 4966 4967 4968 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 4969 { 4970 struct wpa_ctrl_dst *dst, *prev; 4971 4972 if (hapd->ctrl_sock > -1) { 4973 #ifndef CONFIG_CTRL_IFACE_UDP 4974 char *fname; 4975 #endif /* !CONFIG_CTRL_IFACE_UDP */ 4976 4977 eloop_unregister_read_sock(hapd->ctrl_sock); 4978 close(hapd->ctrl_sock); 4979 hapd->ctrl_sock = -1; 4980 #ifndef CONFIG_CTRL_IFACE_UDP 4981 fname = hostapd_ctrl_iface_path(hapd); 4982 if (fname) 4983 unlink(fname); 4984 os_free(fname); 4985 4986 if (hapd->conf->ctrl_interface && 4987 rmdir(hapd->conf->ctrl_interface) < 0) { 4988 if (errno == ENOTEMPTY) { 4989 wpa_printf(MSG_DEBUG, "Control interface " 4990 "directory not empty - leaving it " 4991 "behind"); 4992 } else { 4993 wpa_printf(MSG_ERROR, 4994 "rmdir[ctrl_interface=%s]: %s", 4995 hapd->conf->ctrl_interface, 4996 strerror(errno)); 4997 } 4998 } 4999 #endif /* !CONFIG_CTRL_IFACE_UDP */ 5000 } 5001 5002 dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst, 5003 list) 5004 os_free(dst); 5005 5006 #ifdef CONFIG_TESTING_OPTIONS 5007 l2_packet_deinit(hapd->l2_test); 5008 hapd->l2_test = NULL; 5009 #endif /* CONFIG_TESTING_OPTIONS */ 5010 } 5011 5012 5013 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 5014 char *buf) 5015 { 5016 if (hostapd_add_iface(interfaces, buf) < 0) { 5017 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 5018 return -1; 5019 } 5020 return 0; 5021 } 5022 5023 5024 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 5025 char *buf) 5026 { 5027 if (hostapd_remove_iface(interfaces, buf) < 0) { 5028 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 5029 return -1; 5030 } 5031 return 0; 5032 } 5033 5034 5035 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces, 5036 struct sockaddr_storage *from, 5037 socklen_t fromlen, char *input) 5038 { 5039 return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen, 5040 input); 5041 } 5042 5043 5044 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces, 5045 struct sockaddr_storage *from, 5046 socklen_t fromlen) 5047 { 5048 return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen); 5049 } 5050 5051 5052 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 5053 { 5054 #ifdef CONFIG_WPS_TESTING 5055 wps_version_number = 0x20; 5056 wps_testing_stub_cred = 0; 5057 wps_corrupt_pkhash = 0; 5058 #endif /* CONFIG_WPS_TESTING */ 5059 5060 #ifdef CONFIG_TESTING_OPTIONS 5061 #ifdef CONFIG_DPP 5062 dpp_test = DPP_TEST_DISABLED; 5063 #ifdef CONFIG_DPP3 5064 dpp_version_override = 3; 5065 #elif defined(CONFIG_DPP2) 5066 dpp_version_override = 2; 5067 #else /* CONFIG_DPP2 */ 5068 dpp_version_override = 1; 5069 #endif /* CONFIG_DPP2 */ 5070 #endif /* CONFIG_DPP */ 5071 #endif /* CONFIG_TESTING_OPTIONS */ 5072 5073 #ifdef CONFIG_DPP 5074 dpp_global_clear(interfaces->dpp); 5075 #ifdef CONFIG_DPP3 5076 interfaces->dpp_pb_bi = NULL; 5077 { 5078 int i; 5079 5080 for (i = 0; i < DPP_PB_INFO_COUNT; i++) { 5081 struct dpp_pb_info *info; 5082 5083 info = &interfaces->dpp_pb[i]; 5084 info->rx_time.sec = 0; 5085 info->rx_time.usec = 0; 5086 } 5087 } 5088 #endif /* CONFIG_DPP3 */ 5089 #endif /* CONFIG_DPP */ 5090 } 5091 5092 5093 #ifdef CONFIG_FST 5094 5095 static int 5096 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces, 5097 const char *cmd) 5098 { 5099 char ifname[IFNAMSIZ + 1]; 5100 struct fst_iface_cfg cfg; 5101 struct hostapd_data *hapd; 5102 struct fst_wpa_obj iface_obj; 5103 5104 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 5105 hapd = hostapd_get_iface(interfaces, ifname); 5106 if (hapd) { 5107 if (hapd->iface->fst) { 5108 wpa_printf(MSG_INFO, "FST: Already attached"); 5109 return -1; 5110 } 5111 fst_hostapd_fill_iface_obj(hapd, &iface_obj); 5112 hapd->iface->fst = fst_attach(ifname, hapd->own_addr, 5113 &iface_obj, &cfg); 5114 if (hapd->iface->fst) 5115 return 0; 5116 } 5117 } 5118 5119 return -EINVAL; 5120 } 5121 5122 5123 static int 5124 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces, 5125 const char *cmd) 5126 { 5127 char ifname[IFNAMSIZ + 1]; 5128 struct hostapd_data * hapd; 5129 5130 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 5131 hapd = hostapd_get_iface(interfaces, ifname); 5132 if (hapd) { 5133 if (!fst_iface_detach(ifname)) { 5134 hapd->iface->fst = NULL; 5135 hapd->iface->fst_ies = NULL; 5136 return 0; 5137 } 5138 } 5139 } 5140 5141 return -EINVAL; 5142 } 5143 5144 #endif /* CONFIG_FST */ 5145 5146 5147 static struct hostapd_data * 5148 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces, 5149 const char *ifname) 5150 { 5151 size_t i, j; 5152 5153 for (i = 0; i < interfaces->count; i++) { 5154 struct hostapd_iface *iface = interfaces->iface[i]; 5155 5156 for (j = 0; j < iface->num_bss; j++) { 5157 struct hostapd_data *hapd; 5158 5159 hapd = iface->bss[j]; 5160 if (os_strcmp(ifname, hapd->conf->iface) == 0) 5161 return hapd; 5162 } 5163 } 5164 5165 return NULL; 5166 } 5167 5168 5169 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd, 5170 struct hostapd_data *dst_hapd, 5171 const char *param) 5172 { 5173 int res; 5174 char *value; 5175 5176 value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 5177 if (!value) { 5178 wpa_printf(MSG_ERROR, 5179 "DUP: cannot allocate buffer to stringify %s", 5180 param); 5181 goto error_return; 5182 } 5183 5184 if (os_strcmp(param, "wpa") == 0) { 5185 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d", 5186 src_hapd->conf->wpa); 5187 } else if (os_strcmp(param, "wpa_key_mgmt") == 0 && 5188 src_hapd->conf->wpa_key_mgmt) { 5189 res = hostapd_ctrl_iface_get_key_mgmt( 5190 src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 5191 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res)) 5192 goto error_stringify; 5193 } else if (os_strcmp(param, "wpa_pairwise") == 0 && 5194 src_hapd->conf->wpa_pairwise) { 5195 res = wpa_write_ciphers(value, 5196 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 5197 src_hapd->conf->wpa_pairwise, " "); 5198 if (res < 0) 5199 goto error_stringify; 5200 } else if (os_strcmp(param, "rsn_pairwise") == 0 && 5201 src_hapd->conf->rsn_pairwise) { 5202 res = wpa_write_ciphers(value, 5203 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 5204 src_hapd->conf->rsn_pairwise, " "); 5205 if (res < 0) 5206 goto error_stringify; 5207 } else if (os_strcmp(param, "wpa_passphrase") == 0 && 5208 src_hapd->conf->ssid.wpa_passphrase) { 5209 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s", 5210 src_hapd->conf->ssid.wpa_passphrase); 5211 } else if (os_strcmp(param, "wpa_psk") == 0 && 5212 src_hapd->conf->ssid.wpa_psk_set) { 5213 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 5214 src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 5215 } else { 5216 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param); 5217 goto error_return; 5218 } 5219 5220 res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value); 5221 os_free(value); 5222 return res; 5223 5224 error_stringify: 5225 wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param); 5226 error_return: 5227 os_free(value); 5228 return -1; 5229 } 5230 5231 5232 static int 5233 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces, 5234 const char *input, 5235 char *reply, int reply_size) 5236 { 5237 size_t i, j; 5238 int res; 5239 char *pos, *end; 5240 struct hostapd_iface *iface; 5241 int show_ctrl = 0; 5242 5243 if (input) 5244 show_ctrl = !!os_strstr(input, "ctrl"); 5245 5246 pos = reply; 5247 end = reply + reply_size; 5248 5249 for (i = 0; i < interfaces->count; i++) { 5250 iface = interfaces->iface[i]; 5251 5252 for (j = 0; j < iface->num_bss; j++) { 5253 struct hostapd_bss_config *conf; 5254 5255 conf = iface->conf->bss[j]; 5256 if (show_ctrl) 5257 res = os_snprintf(pos, end - pos, 5258 "%s ctrl_iface=%s\n", 5259 conf->iface, 5260 conf->ctrl_interface ? 5261 conf->ctrl_interface : "N/A"); 5262 else 5263 res = os_snprintf(pos, end - pos, "%s\n", 5264 conf->iface); 5265 if (os_snprintf_error(end - pos, res)) { 5266 *pos = '\0'; 5267 return pos - reply; 5268 } 5269 pos += res; 5270 } 5271 } 5272 5273 return pos - reply; 5274 } 5275 5276 5277 static int 5278 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces, 5279 char *cmd) 5280 { 5281 char *p_start = cmd, *p_end; 5282 struct hostapd_data *src_hapd, *dst_hapd; 5283 5284 /* cmd: "<src ifname> <dst ifname> <variable name> */ 5285 5286 p_end = os_strchr(p_start, ' '); 5287 if (!p_end) { 5288 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'", 5289 cmd); 5290 return -1; 5291 } 5292 5293 *p_end = '\0'; 5294 src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 5295 if (!src_hapd) { 5296 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'", 5297 p_start); 5298 return -1; 5299 } 5300 5301 p_start = p_end + 1; 5302 p_end = os_strchr(p_start, ' '); 5303 if (!p_end) { 5304 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'", 5305 cmd); 5306 return -1; 5307 } 5308 5309 *p_end = '\0'; 5310 dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 5311 if (!dst_hapd) { 5312 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'", 5313 p_start); 5314 return -1; 5315 } 5316 5317 p_start = p_end + 1; 5318 return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start); 5319 } 5320 5321 5322 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces, 5323 const char *ifname, 5324 char *buf, char *reply, 5325 int reply_size, 5326 struct sockaddr_storage *from, 5327 socklen_t fromlen) 5328 { 5329 struct hostapd_data *hapd; 5330 5331 hapd = hostapd_interfaces_get_hapd(interfaces, ifname); 5332 if (hapd == NULL) { 5333 int res; 5334 5335 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n"); 5336 if (os_snprintf_error(reply_size, res)) 5337 return -1; 5338 return res; 5339 } 5340 5341 return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size, 5342 from, fromlen); 5343 } 5344 5345 5346 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 5347 void *sock_ctx) 5348 { 5349 struct hapd_interfaces *interfaces = eloop_ctx; 5350 char buffer[256], *buf = buffer; 5351 int res; 5352 struct sockaddr_storage from; 5353 socklen_t fromlen = sizeof(from); 5354 char *reply; 5355 int reply_len; 5356 const int reply_size = 4096; 5357 #ifdef CONFIG_CTRL_IFACE_UDP 5358 unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; 5359 #endif /* CONFIG_CTRL_IFACE_UDP */ 5360 5361 res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, 5362 (struct sockaddr *) &from, &fromlen); 5363 if (res < 0) { 5364 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 5365 strerror(errno)); 5366 return; 5367 } 5368 buf[res] = '\0'; 5369 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 5370 5371 reply = os_malloc(reply_size); 5372 if (reply == NULL) { 5373 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 5374 fromlen) < 0) { 5375 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 5376 strerror(errno)); 5377 } 5378 return; 5379 } 5380 5381 os_memcpy(reply, "OK\n", 3); 5382 reply_len = 3; 5383 5384 #ifdef CONFIG_CTRL_IFACE_UDP 5385 if (os_strcmp(buf, "GET_COOKIE") == 0) { 5386 os_memcpy(reply, "COOKIE=", 7); 5387 wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, 5388 interfaces->ctrl_iface_cookie, 5389 CTRL_IFACE_COOKIE_LEN); 5390 reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; 5391 goto send_reply; 5392 } 5393 5394 if (os_strncmp(buf, "COOKIE=", 7) != 0 || 5395 hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { 5396 wpa_printf(MSG_DEBUG, 5397 "CTRL: No cookie in the request - drop request"); 5398 os_free(reply); 5399 return; 5400 } 5401 5402 if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie, 5403 CTRL_IFACE_COOKIE_LEN) != 0) { 5404 wpa_printf(MSG_DEBUG, 5405 "CTRL: Invalid cookie in the request - drop request"); 5406 os_free(reply); 5407 return; 5408 } 5409 5410 buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN; 5411 while (*buf == ' ') 5412 buf++; 5413 #endif /* CONFIG_CTRL_IFACE_UDP */ 5414 5415 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 5416 char *pos = os_strchr(buf + 7, ' '); 5417 5418 if (pos) { 5419 *pos++ = '\0'; 5420 reply_len = hostapd_global_ctrl_iface_ifname( 5421 interfaces, buf + 7, pos, reply, reply_size, 5422 &from, fromlen); 5423 goto send_reply; 5424 } 5425 } 5426 5427 if (os_strcmp(buf, "PING") == 0) { 5428 os_memcpy(reply, "PONG\n", 5); 5429 reply_len = 5; 5430 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 5431 if (wpa_debug_reopen_file() < 0) 5432 reply_len = -1; 5433 } else if (os_strcmp(buf, "FLUSH") == 0) { 5434 hostapd_ctrl_iface_flush(interfaces); 5435 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 5436 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 5437 reply_len = -1; 5438 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 5439 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 5440 reply_len = -1; 5441 } else if (os_strcmp(buf, "ATTACH") == 0) { 5442 if (hostapd_global_ctrl_iface_attach(interfaces, &from, 5443 fromlen, NULL)) 5444 reply_len = -1; 5445 } else if (os_strncmp(buf, "ATTACH ", 7) == 0) { 5446 if (hostapd_global_ctrl_iface_attach(interfaces, &from, 5447 fromlen, buf + 7)) 5448 reply_len = -1; 5449 } else if (os_strcmp(buf, "DETACH") == 0) { 5450 if (hostapd_global_ctrl_iface_detach(interfaces, &from, 5451 fromlen)) 5452 reply_len = -1; 5453 #ifdef CONFIG_MODULE_TESTS 5454 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 5455 if (hapd_module_tests() < 0) 5456 reply_len = -1; 5457 #endif /* CONFIG_MODULE_TESTS */ 5458 #ifdef CONFIG_FST 5459 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 5460 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11)) 5461 reply_len = os_snprintf(reply, reply_size, "OK\n"); 5462 else 5463 reply_len = -1; 5464 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 5465 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11)) 5466 reply_len = os_snprintf(reply, reply_size, "OK\n"); 5467 else 5468 reply_len = -1; 5469 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 5470 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 5471 #endif /* CONFIG_FST */ 5472 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 5473 if (!hostapd_global_ctrl_iface_dup_network(interfaces, 5474 buf + 12)) 5475 reply_len = os_snprintf(reply, reply_size, "OK\n"); 5476 else 5477 reply_len = -1; 5478 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 5479 reply_len = hostapd_global_ctrl_iface_interfaces( 5480 interfaces, buf + 10, reply, reply_size); 5481 } else if (os_strcmp(buf, "TERMINATE") == 0) { 5482 eloop_terminate(); 5483 } else { 5484 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 5485 "ignored"); 5486 reply_len = -1; 5487 } 5488 5489 send_reply: 5490 if (reply_len < 0) { 5491 os_memcpy(reply, "FAIL\n", 5); 5492 reply_len = 5; 5493 } 5494 5495 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 5496 fromlen) < 0) { 5497 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 5498 strerror(errno)); 5499 } 5500 os_free(reply); 5501 } 5502 5503 5504 #ifndef CONFIG_CTRL_IFACE_UDP 5505 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 5506 { 5507 char *buf; 5508 size_t len; 5509 5510 if (interface->global_iface_path == NULL) 5511 return NULL; 5512 5513 len = os_strlen(interface->global_iface_path) + 5514 os_strlen(interface->global_iface_name) + 2; 5515 buf = os_malloc(len); 5516 if (buf == NULL) 5517 return NULL; 5518 5519 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 5520 interface->global_iface_name); 5521 buf[len - 1] = '\0'; 5522 return buf; 5523 } 5524 #endif /* CONFIG_CTRL_IFACE_UDP */ 5525 5526 5527 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 5528 { 5529 #ifdef CONFIG_CTRL_IFACE_UDP 5530 int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT; 5531 char p[32] = { 0 }; 5532 char *pos; 5533 struct addrinfo hints = { 0 }, *res, *saveres; 5534 int n; 5535 5536 if (interface->global_ctrl_sock > -1) { 5537 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 5538 return 0; 5539 } 5540 5541 if (interface->global_iface_path == NULL) 5542 return 0; 5543 5544 pos = os_strstr(interface->global_iface_path, "udp:"); 5545 if (pos) { 5546 pos += 4; 5547 port = atoi(pos); 5548 if (port <= 0) { 5549 wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port"); 5550 goto fail; 5551 } 5552 } 5553 5554 os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); 5555 5556 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 5557 hints.ai_flags = AI_PASSIVE; 5558 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 5559 5560 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 5561 hints.ai_family = AF_INET6; 5562 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 5563 hints.ai_family = AF_INET; 5564 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 5565 hints.ai_socktype = SOCK_DGRAM; 5566 5567 try_again: 5568 os_snprintf(p, sizeof(p), "%d", port); 5569 n = getaddrinfo(NULL, p, &hints, &res); 5570 if (n) { 5571 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 5572 goto fail; 5573 } 5574 5575 saveres = res; 5576 interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype, 5577 res->ai_protocol); 5578 if (interface->global_ctrl_sock < 0) { 5579 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 5580 goto fail; 5581 } 5582 5583 if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) < 5584 0) { 5585 port++; 5586 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) < 5587 HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos) 5588 goto try_again; 5589 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 5590 goto fail; 5591 } 5592 5593 freeaddrinfo(saveres); 5594 5595 wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port); 5596 5597 if (eloop_register_read_sock(interface->global_ctrl_sock, 5598 hostapd_global_ctrl_iface_receive, 5599 interface, NULL) < 0) { 5600 hostapd_global_ctrl_iface_deinit(interface); 5601 return -1; 5602 } 5603 5604 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 5605 5606 return 0; 5607 5608 fail: 5609 if (interface->global_ctrl_sock >= 0) 5610 close(interface->global_ctrl_sock); 5611 return -1; 5612 #else /* CONFIG_CTRL_IFACE_UDP */ 5613 struct sockaddr_un addr; 5614 int s = -1; 5615 char *fname = NULL; 5616 5617 if (interface->global_iface_path == NULL) { 5618 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 5619 return 0; 5620 } 5621 5622 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 5623 if (errno == EEXIST) { 5624 wpa_printf(MSG_DEBUG, "Using existing control " 5625 "interface directory."); 5626 } else { 5627 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 5628 strerror(errno)); 5629 goto fail; 5630 } 5631 } else if (interface->ctrl_iface_group && 5632 lchown(interface->global_iface_path, -1, 5633 interface->ctrl_iface_group) < 0) { 5634 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 5635 strerror(errno)); 5636 goto fail; 5637 } 5638 5639 if (os_strlen(interface->global_iface_path) + 1 + 5640 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 5641 goto fail; 5642 5643 s = socket(PF_UNIX, SOCK_DGRAM, 0); 5644 if (s < 0) { 5645 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 5646 goto fail; 5647 } 5648 5649 os_memset(&addr, 0, sizeof(addr)); 5650 #ifdef __FreeBSD__ 5651 addr.sun_len = sizeof(addr); 5652 #endif /* __FreeBSD__ */ 5653 addr.sun_family = AF_UNIX; 5654 fname = hostapd_global_ctrl_iface_path(interface); 5655 if (fname == NULL) 5656 goto fail; 5657 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 5658 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 5659 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 5660 strerror(errno)); 5661 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 5662 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 5663 " allow connections - assuming it was left" 5664 "over from forced program termination"); 5665 if (unlink(fname) < 0) { 5666 wpa_printf(MSG_ERROR, 5667 "Could not unlink existing ctrl_iface socket '%s': %s", 5668 fname, strerror(errno)); 5669 goto fail; 5670 } 5671 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 5672 0) { 5673 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s", 5674 strerror(errno)); 5675 goto fail; 5676 } 5677 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 5678 "ctrl_iface socket '%s'", fname); 5679 } else { 5680 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 5681 "be in use - cannot override it"); 5682 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 5683 "not used anymore", fname); 5684 os_free(fname); 5685 fname = NULL; 5686 goto fail; 5687 } 5688 } 5689 5690 if (interface->ctrl_iface_group && 5691 lchown(fname, -1, interface->ctrl_iface_group) < 0) { 5692 wpa_printf(MSG_ERROR, "lchown[ctrl_interface]: %s", 5693 strerror(errno)); 5694 goto fail; 5695 } 5696 5697 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 5698 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 5699 strerror(errno)); 5700 goto fail; 5701 } 5702 os_free(fname); 5703 5704 interface->global_ctrl_sock = s; 5705 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 5706 interface, NULL); 5707 5708 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 5709 5710 return 0; 5711 5712 fail: 5713 if (s >= 0) 5714 close(s); 5715 if (fname) { 5716 unlink(fname); 5717 os_free(fname); 5718 } 5719 return -1; 5720 #endif /* CONFIG_CTRL_IFACE_UDP */ 5721 } 5722 5723 5724 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 5725 { 5726 #ifndef CONFIG_CTRL_IFACE_UDP 5727 char *fname = NULL; 5728 #endif /* CONFIG_CTRL_IFACE_UDP */ 5729 struct wpa_ctrl_dst *dst, *prev; 5730 5731 if (interfaces->global_ctrl_sock > -1) { 5732 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 5733 close(interfaces->global_ctrl_sock); 5734 interfaces->global_ctrl_sock = -1; 5735 #ifndef CONFIG_CTRL_IFACE_UDP 5736 fname = hostapd_global_ctrl_iface_path(interfaces); 5737 if (fname) { 5738 unlink(fname); 5739 os_free(fname); 5740 } 5741 5742 if (interfaces->global_iface_path && 5743 rmdir(interfaces->global_iface_path) < 0) { 5744 if (errno == ENOTEMPTY) { 5745 wpa_printf(MSG_DEBUG, "Control interface " 5746 "directory not empty - leaving it " 5747 "behind"); 5748 } else { 5749 wpa_printf(MSG_ERROR, 5750 "rmdir[ctrl_interface=%s]: %s", 5751 interfaces->global_iface_path, 5752 strerror(errno)); 5753 } 5754 } 5755 #endif /* CONFIG_CTRL_IFACE_UDP */ 5756 } 5757 5758 os_free(interfaces->global_iface_path); 5759 interfaces->global_iface_path = NULL; 5760 5761 dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst, 5762 struct wpa_ctrl_dst, list) 5763 os_free(dst); 5764 } 5765 5766 5767 static int hostapd_ctrl_check_event_enabled(struct wpa_ctrl_dst *dst, 5768 const char *buf) 5769 { 5770 /* Enable Probe Request events based on explicit request. 5771 * Other events are enabled by default. 5772 */ 5773 if (str_starts(buf, RX_PROBE_REQUEST)) 5774 return !!(dst->events & WPA_EVENT_RX_PROBE_REQUEST); 5775 return 1; 5776 } 5777 5778 5779 static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst, 5780 const char *ifname, int level, 5781 const char *buf, size_t len) 5782 { 5783 struct wpa_ctrl_dst *dst, *next; 5784 struct msghdr msg; 5785 int idx, res; 5786 struct iovec io[5]; 5787 char levelstr[10]; 5788 5789 if (sock < 0 || dl_list_empty(ctrl_dst)) 5790 return; 5791 5792 res = os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 5793 if (os_snprintf_error(sizeof(levelstr), res)) 5794 return; 5795 idx = 0; 5796 if (ifname) { 5797 io[idx].iov_base = "IFNAME="; 5798 io[idx].iov_len = 7; 5799 idx++; 5800 io[idx].iov_base = (char *) ifname; 5801 io[idx].iov_len = os_strlen(ifname); 5802 idx++; 5803 io[idx].iov_base = " "; 5804 io[idx].iov_len = 1; 5805 idx++; 5806 } 5807 io[idx].iov_base = levelstr; 5808 io[idx].iov_len = os_strlen(levelstr); 5809 idx++; 5810 io[idx].iov_base = (char *) buf; 5811 io[idx].iov_len = len; 5812 idx++; 5813 os_memset(&msg, 0, sizeof(msg)); 5814 msg.msg_iov = io; 5815 msg.msg_iovlen = idx; 5816 5817 idx = 0; 5818 dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) { 5819 if ((level >= dst->debug_level) && 5820 hostapd_ctrl_check_event_enabled(dst, buf)) { 5821 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send", 5822 &dst->addr, dst->addrlen); 5823 msg.msg_name = &dst->addr; 5824 msg.msg_namelen = dst->addrlen; 5825 if (sendmsg(sock, &msg, 0) < 0) { 5826 int _errno = errno; 5827 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 5828 "%d - %s", 5829 idx, errno, strerror(errno)); 5830 dst->errors++; 5831 if (dst->errors > 10 || _errno == ENOENT) { 5832 ctrl_iface_detach(ctrl_dst, 5833 &dst->addr, 5834 dst->addrlen); 5835 } 5836 } else 5837 dst->errors = 0; 5838 } 5839 idx++; 5840 } 5841 } 5842 5843 5844 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 5845 enum wpa_msg_type type, 5846 const char *buf, size_t len) 5847 { 5848 if (type != WPA_MSG_NO_GLOBAL) { 5849 hostapd_ctrl_iface_send_internal( 5850 hapd->iface->interfaces->global_ctrl_sock, 5851 &hapd->iface->interfaces->global_ctrl_dst, 5852 type != WPA_MSG_PER_INTERFACE ? 5853 NULL : hapd->conf->iface, 5854 level, buf, len); 5855 } 5856 5857 if (type != WPA_MSG_ONLY_GLOBAL) { 5858 hostapd_ctrl_iface_send_internal( 5859 hapd->ctrl_sock, &hapd->ctrl_dst, 5860 NULL, level, buf, len); 5861 } 5862 } 5863 5864 #endif /* CONFIG_NATIVE_WINDOWS */ 5865