1 /* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2015, Jouni Malinen <j (at) 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 #include <net/ethernet.h> 15 #include <netinet/ip.h> 16 #endif /* CONFIG_TESTING_OPTIONS */ 17 18 #include <sys/un.h> 19 #include <sys/stat.h> 20 #include <stddef.h> 21 22 #ifdef CONFIG_CTRL_IFACE_UDP 23 #include <netdb.h> 24 #endif /* CONFIG_CTRL_IFACE_UDP */ 25 26 #include "utils/common.h" 27 #include "utils/eloop.h" 28 #include "utils/module_tests.h" 29 #include "common/version.h" 30 #include "common/ieee802_11_defs.h" 31 #include "common/ctrl_iface_common.h" 32 #include "crypto/tls.h" 33 #include "drivers/driver.h" 34 #include "eapol_auth/eapol_auth_sm.h" 35 #include "radius/radius_client.h" 36 #include "radius/radius_server.h" 37 #include "l2_packet/l2_packet.h" 38 #include "ap/hostapd.h" 39 #include "ap/ap_config.h" 40 #include "ap/ieee802_1x.h" 41 #include "ap/wpa_auth.h" 42 #include "ap/ieee802_11.h" 43 #include "ap/sta_info.h" 44 #include "ap/wps_hostapd.h" 45 #include "ap/ctrl_iface_ap.h" 46 #include "ap/ap_drv_ops.h" 47 #include "ap/hs20.h" 48 #include "ap/wnm_ap.h" 49 #include "ap/wpa_auth.h" 50 #include "ap/beacon.h" 51 #include "ap/neighbor_db.h" 52 #include "ap/rrm.h" 53 #include "wps/wps_defs.h" 54 #include "wps/wps.h" 55 #include "fst/fst_ctrl_iface.h" 56 #include "config_file.h" 57 #include "ctrl_iface.h" 58 59 60 #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 61 62 #ifdef CONFIG_CTRL_IFACE_UDP 63 #define COOKIE_LEN 8 64 static unsigned char cookie[COOKIE_LEN]; 65 static unsigned char gcookie[COOKIE_LEN]; 66 #define HOSTAPD_CTRL_IFACE_PORT 8877 67 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50 68 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878 69 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50 70 #endif /* CONFIG_CTRL_IFACE_UDP */ 71 72 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 73 enum wpa_msg_type type, 74 const char *buf, size_t len); 75 76 77 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 78 struct sockaddr_storage *from, 79 socklen_t fromlen) 80 { 81 return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen); 82 } 83 84 85 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 86 struct sockaddr_storage *from, 87 socklen_t fromlen) 88 { 89 return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen); 90 } 91 92 93 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 94 struct sockaddr_storage *from, 95 socklen_t fromlen, 96 char *level) 97 { 98 return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level); 99 } 100 101 102 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 103 const char *txtaddr) 104 { 105 u8 addr[ETH_ALEN]; 106 struct sta_info *sta; 107 108 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 109 110 if (hwaddr_aton(txtaddr, addr)) 111 return -1; 112 113 sta = ap_get_sta(hapd, addr); 114 if (sta) 115 return 0; 116 117 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 118 "notification", MAC2STR(addr)); 119 sta = ap_sta_add(hapd, addr); 120 if (sta == NULL) 121 return -1; 122 123 hostapd_new_assoc_sta(hapd, sta, 0); 124 return 0; 125 } 126 127 128 #ifdef CONFIG_IEEE80211W 129 #ifdef NEED_AP_MLME 130 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 131 const char *txtaddr) 132 { 133 u8 addr[ETH_ALEN]; 134 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 135 136 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 137 138 if (hwaddr_aton(txtaddr, addr) || 139 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 140 return -1; 141 142 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 143 144 return 0; 145 } 146 #endif /* NEED_AP_MLME */ 147 #endif /* CONFIG_IEEE80211W */ 148 149 150 #ifdef CONFIG_WPS 151 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 152 { 153 char *pin = os_strchr(txt, ' '); 154 char *timeout_txt; 155 int timeout; 156 u8 addr_buf[ETH_ALEN], *addr = NULL; 157 char *pos; 158 159 if (pin == NULL) 160 return -1; 161 *pin++ = '\0'; 162 163 timeout_txt = os_strchr(pin, ' '); 164 if (timeout_txt) { 165 *timeout_txt++ = '\0'; 166 timeout = atoi(timeout_txt); 167 pos = os_strchr(timeout_txt, ' '); 168 if (pos) { 169 *pos++ = '\0'; 170 if (hwaddr_aton(pos, addr_buf) == 0) 171 addr = addr_buf; 172 } 173 } else 174 timeout = 0; 175 176 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 177 } 178 179 180 static int hostapd_ctrl_iface_wps_check_pin( 181 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 182 { 183 char pin[9]; 184 size_t len; 185 char *pos; 186 int ret; 187 188 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 189 (u8 *) cmd, os_strlen(cmd)); 190 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 191 if (*pos < '0' || *pos > '9') 192 continue; 193 pin[len++] = *pos; 194 if (len == 9) { 195 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 196 return -1; 197 } 198 } 199 if (len != 4 && len != 8) { 200 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 201 return -1; 202 } 203 pin[len] = '\0'; 204 205 if (len == 8) { 206 unsigned int pin_val; 207 pin_val = atoi(pin); 208 if (!wps_pin_valid(pin_val)) { 209 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 210 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 211 if (os_snprintf_error(buflen, ret)) 212 return -1; 213 return ret; 214 } 215 } 216 217 ret = os_snprintf(buf, buflen, "%s", pin); 218 if (os_snprintf_error(buflen, ret)) 219 return -1; 220 221 return ret; 222 } 223 224 225 #ifdef CONFIG_WPS_NFC 226 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 227 char *pos) 228 { 229 size_t len; 230 struct wpabuf *buf; 231 int ret; 232 233 len = os_strlen(pos); 234 if (len & 0x01) 235 return -1; 236 len /= 2; 237 238 buf = wpabuf_alloc(len); 239 if (buf == NULL) 240 return -1; 241 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 242 wpabuf_free(buf); 243 return -1; 244 } 245 246 ret = hostapd_wps_nfc_tag_read(hapd, buf); 247 wpabuf_free(buf); 248 249 return ret; 250 } 251 252 253 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 254 char *cmd, char *reply, 255 size_t max_len) 256 { 257 int ndef; 258 struct wpabuf *buf; 259 int res; 260 261 if (os_strcmp(cmd, "WPS") == 0) 262 ndef = 0; 263 else if (os_strcmp(cmd, "NDEF") == 0) 264 ndef = 1; 265 else 266 return -1; 267 268 buf = hostapd_wps_nfc_config_token(hapd, ndef); 269 if (buf == NULL) 270 return -1; 271 272 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 273 wpabuf_len(buf)); 274 reply[res++] = '\n'; 275 reply[res] = '\0'; 276 277 wpabuf_free(buf); 278 279 return res; 280 } 281 282 283 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 284 char *reply, size_t max_len, 285 int ndef) 286 { 287 struct wpabuf *buf; 288 int res; 289 290 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 291 if (buf == NULL) 292 return -1; 293 294 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 295 wpabuf_len(buf)); 296 reply[res++] = '\n'; 297 reply[res] = '\0'; 298 299 wpabuf_free(buf); 300 301 return res; 302 } 303 304 305 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 306 char *cmd, char *reply, 307 size_t max_len) 308 { 309 if (os_strcmp(cmd, "WPS") == 0) 310 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 311 max_len, 0); 312 313 if (os_strcmp(cmd, "NDEF") == 0) 314 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 315 max_len, 1); 316 317 if (os_strcmp(cmd, "enable") == 0) 318 return hostapd_wps_nfc_token_enable(hapd); 319 320 if (os_strcmp(cmd, "disable") == 0) { 321 hostapd_wps_nfc_token_disable(hapd); 322 return 0; 323 } 324 325 return -1; 326 } 327 328 329 static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 330 char *cmd, char *reply, 331 size_t max_len) 332 { 333 struct wpabuf *buf; 334 int res; 335 char *pos; 336 int ndef; 337 338 pos = os_strchr(cmd, ' '); 339 if (pos == NULL) 340 return -1; 341 *pos++ = '\0'; 342 343 if (os_strcmp(cmd, "WPS") == 0) 344 ndef = 0; 345 else if (os_strcmp(cmd, "NDEF") == 0) 346 ndef = 1; 347 else 348 return -1; 349 350 if (os_strcmp(pos, "WPS-CR") == 0) 351 buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 352 else 353 buf = NULL; 354 if (buf == NULL) 355 return -1; 356 357 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 358 wpabuf_len(buf)); 359 reply[res++] = '\n'; 360 reply[res] = '\0'; 361 362 wpabuf_free(buf); 363 364 return res; 365 } 366 367 368 static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 369 char *cmd) 370 { 371 size_t len; 372 struct wpabuf *req, *sel; 373 int ret; 374 char *pos, *role, *type, *pos2; 375 376 role = cmd; 377 pos = os_strchr(role, ' '); 378 if (pos == NULL) 379 return -1; 380 *pos++ = '\0'; 381 382 type = pos; 383 pos = os_strchr(type, ' '); 384 if (pos == NULL) 385 return -1; 386 *pos++ = '\0'; 387 388 pos2 = os_strchr(pos, ' '); 389 if (pos2 == NULL) 390 return -1; 391 *pos2++ = '\0'; 392 393 len = os_strlen(pos); 394 if (len & 0x01) 395 return -1; 396 len /= 2; 397 398 req = wpabuf_alloc(len); 399 if (req == NULL) 400 return -1; 401 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 402 wpabuf_free(req); 403 return -1; 404 } 405 406 len = os_strlen(pos2); 407 if (len & 0x01) { 408 wpabuf_free(req); 409 return -1; 410 } 411 len /= 2; 412 413 sel = wpabuf_alloc(len); 414 if (sel == NULL) { 415 wpabuf_free(req); 416 return -1; 417 } 418 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 419 wpabuf_free(req); 420 wpabuf_free(sel); 421 return -1; 422 } 423 424 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 425 ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 426 } else { 427 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 428 "reported: role=%s type=%s", role, type); 429 ret = -1; 430 } 431 wpabuf_free(req); 432 wpabuf_free(sel); 433 434 return ret; 435 } 436 437 #endif /* CONFIG_WPS_NFC */ 438 439 440 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 441 char *buf, size_t buflen) 442 { 443 int timeout = 300; 444 char *pos; 445 const char *pin_txt; 446 447 pos = os_strchr(txt, ' '); 448 if (pos) 449 *pos++ = '\0'; 450 451 if (os_strcmp(txt, "disable") == 0) { 452 hostapd_wps_ap_pin_disable(hapd); 453 return os_snprintf(buf, buflen, "OK\n"); 454 } 455 456 if (os_strcmp(txt, "random") == 0) { 457 if (pos) 458 timeout = atoi(pos); 459 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 460 if (pin_txt == NULL) 461 return -1; 462 return os_snprintf(buf, buflen, "%s", pin_txt); 463 } 464 465 if (os_strcmp(txt, "get") == 0) { 466 pin_txt = hostapd_wps_ap_pin_get(hapd); 467 if (pin_txt == NULL) 468 return -1; 469 return os_snprintf(buf, buflen, "%s", pin_txt); 470 } 471 472 if (os_strcmp(txt, "set") == 0) { 473 char *pin; 474 if (pos == NULL) 475 return -1; 476 pin = pos; 477 pos = os_strchr(pos, ' '); 478 if (pos) { 479 *pos++ = '\0'; 480 timeout = atoi(pos); 481 } 482 if (os_strlen(pin) > buflen) 483 return -1; 484 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 485 return -1; 486 return os_snprintf(buf, buflen, "%s", pin); 487 } 488 489 return -1; 490 } 491 492 493 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 494 { 495 char *pos; 496 char *ssid, *auth, *encr = NULL, *key = NULL; 497 498 ssid = txt; 499 pos = os_strchr(txt, ' '); 500 if (!pos) 501 return -1; 502 *pos++ = '\0'; 503 504 auth = pos; 505 pos = os_strchr(pos, ' '); 506 if (pos) { 507 *pos++ = '\0'; 508 encr = pos; 509 pos = os_strchr(pos, ' '); 510 if (pos) { 511 *pos++ = '\0'; 512 key = pos; 513 } 514 } 515 516 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 517 } 518 519 520 static const char * pbc_status_str(enum pbc_status status) 521 { 522 switch (status) { 523 case WPS_PBC_STATUS_DISABLE: 524 return "Disabled"; 525 case WPS_PBC_STATUS_ACTIVE: 526 return "Active"; 527 case WPS_PBC_STATUS_TIMEOUT: 528 return "Timed-out"; 529 case WPS_PBC_STATUS_OVERLAP: 530 return "Overlap"; 531 default: 532 return "Unknown"; 533 } 534 } 535 536 537 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, 538 char *buf, size_t buflen) 539 { 540 int ret; 541 char *pos, *end; 542 543 pos = buf; 544 end = buf + buflen; 545 546 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", 547 pbc_status_str(hapd->wps_stats.pbc_status)); 548 549 if (os_snprintf_error(end - pos, ret)) 550 return pos - buf; 551 pos += ret; 552 553 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 554 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 555 "Success": 556 (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 557 "Failed" : "None"))); 558 559 if (os_snprintf_error(end - pos, ret)) 560 return pos - buf; 561 pos += ret; 562 563 /* If status == Failure - Add possible Reasons */ 564 if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 565 hapd->wps_stats.failure_reason > 0) { 566 ret = os_snprintf(pos, end - pos, 567 "Failure Reason: %s\n", 568 wps_ei_str(hapd->wps_stats.failure_reason)); 569 570 if (os_snprintf_error(end - pos, ret)) 571 return pos - buf; 572 pos += ret; 573 } 574 575 if (hapd->wps_stats.status) { 576 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 577 MAC2STR(hapd->wps_stats.peer_addr)); 578 579 if (os_snprintf_error(end - pos, ret)) 580 return pos - buf; 581 pos += ret; 582 } 583 584 return pos - buf; 585 } 586 587 #endif /* CONFIG_WPS */ 588 589 #ifdef CONFIG_HS20 590 591 static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 592 const char *cmd) 593 { 594 u8 addr[ETH_ALEN]; 595 const char *url; 596 597 if (hwaddr_aton(cmd, addr)) 598 return -1; 599 url = cmd + 17; 600 if (*url == '\0') { 601 url = NULL; 602 } else { 603 if (*url != ' ') 604 return -1; 605 url++; 606 if (*url == '\0') 607 url = NULL; 608 } 609 610 return hs20_send_wnm_notification(hapd, addr, 1, url); 611 } 612 613 614 static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 615 const char *cmd) 616 { 617 u8 addr[ETH_ALEN]; 618 int code, reauth_delay, ret; 619 const char *pos; 620 size_t url_len; 621 struct wpabuf *req; 622 623 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 624 if (hwaddr_aton(cmd, addr)) 625 return -1; 626 627 pos = os_strchr(cmd, ' '); 628 if (pos == NULL) 629 return -1; 630 pos++; 631 code = atoi(pos); 632 633 pos = os_strchr(pos, ' '); 634 if (pos == NULL) 635 return -1; 636 pos++; 637 reauth_delay = atoi(pos); 638 639 url_len = 0; 640 pos = os_strchr(pos, ' '); 641 if (pos) { 642 pos++; 643 url_len = os_strlen(pos); 644 } 645 646 req = wpabuf_alloc(4 + url_len); 647 if (req == NULL) 648 return -1; 649 wpabuf_put_u8(req, code); 650 wpabuf_put_le16(req, reauth_delay); 651 wpabuf_put_u8(req, url_len); 652 if (pos) 653 wpabuf_put_data(req, pos, url_len); 654 655 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 656 " to indicate imminent deauthentication (code=%d " 657 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 658 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 659 wpabuf_free(req); 660 return ret; 661 } 662 663 #endif /* CONFIG_HS20 */ 664 665 666 #ifdef CONFIG_INTERWORKING 667 668 static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 669 const char *cmd) 670 { 671 u8 qos_map_set[16 + 2 * 21], count = 0; 672 const char *pos = cmd; 673 int val, ret; 674 675 for (;;) { 676 if (count == sizeof(qos_map_set)) { 677 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 678 return -1; 679 } 680 681 val = atoi(pos); 682 if (val < 0 || val > 255) { 683 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 684 return -1; 685 } 686 687 qos_map_set[count++] = val; 688 pos = os_strchr(pos, ','); 689 if (!pos) 690 break; 691 pos++; 692 } 693 694 if (count < 16 || count & 1) { 695 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 696 return -1; 697 } 698 699 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 700 if (ret) { 701 wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 702 return -1; 703 } 704 705 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 706 hapd->conf->qos_map_set_len = count; 707 708 return 0; 709 } 710 711 712 static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 713 const char *cmd) 714 { 715 u8 addr[ETH_ALEN]; 716 struct sta_info *sta; 717 struct wpabuf *buf; 718 u8 *qos_map_set = hapd->conf->qos_map_set; 719 u8 qos_map_set_len = hapd->conf->qos_map_set_len; 720 int ret; 721 722 if (!qos_map_set_len) { 723 wpa_printf(MSG_INFO, "QoS Map Set is not set"); 724 return -1; 725 } 726 727 if (hwaddr_aton(cmd, addr)) 728 return -1; 729 730 sta = ap_get_sta(hapd, addr); 731 if (sta == NULL) { 732 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 733 "for QoS Map Configuration message", 734 MAC2STR(addr)); 735 return -1; 736 } 737 738 if (!sta->qos_map_enabled) { 739 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 740 "support for QoS Map", MAC2STR(addr)); 741 return -1; 742 } 743 744 buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 745 if (buf == NULL) 746 return -1; 747 748 wpabuf_put_u8(buf, WLAN_ACTION_QOS); 749 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 750 751 /* QoS Map Set Element */ 752 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 753 wpabuf_put_u8(buf, qos_map_set_len); 754 wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 755 756 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 757 wpabuf_head(buf), wpabuf_len(buf)); 758 wpabuf_free(buf); 759 760 return ret; 761 } 762 763 #endif /* CONFIG_INTERWORKING */ 764 765 766 #ifdef CONFIG_WNM 767 768 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 769 const char *cmd) 770 { 771 u8 addr[ETH_ALEN]; 772 int disassoc_timer; 773 struct sta_info *sta; 774 775 if (hwaddr_aton(cmd, addr)) 776 return -1; 777 if (cmd[17] != ' ') 778 return -1; 779 disassoc_timer = atoi(cmd + 17); 780 781 sta = ap_get_sta(hapd, addr); 782 if (sta == NULL) { 783 wpa_printf(MSG_DEBUG, "Station " MACSTR 784 " not found for disassociation imminent message", 785 MAC2STR(addr)); 786 return -1; 787 } 788 789 return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); 790 } 791 792 793 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 794 const char *cmd) 795 { 796 u8 addr[ETH_ALEN]; 797 const char *url, *timerstr; 798 int disassoc_timer; 799 struct sta_info *sta; 800 801 if (hwaddr_aton(cmd, addr)) 802 return -1; 803 804 sta = ap_get_sta(hapd, addr); 805 if (sta == NULL) { 806 wpa_printf(MSG_DEBUG, "Station " MACSTR 807 " not found for ESS disassociation imminent message", 808 MAC2STR(addr)); 809 return -1; 810 } 811 812 timerstr = cmd + 17; 813 if (*timerstr != ' ') 814 return -1; 815 timerstr++; 816 disassoc_timer = atoi(timerstr); 817 if (disassoc_timer < 0 || disassoc_timer > 65535) 818 return -1; 819 820 url = os_strchr(timerstr, ' '); 821 if (url == NULL) 822 return -1; 823 url++; 824 825 return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); 826 } 827 828 829 static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, 830 const char *cmd) 831 { 832 u8 addr[ETH_ALEN]; 833 const char *pos, *end; 834 int disassoc_timer = 0; 835 struct sta_info *sta; 836 u8 req_mode = 0, valid_int = 0x01; 837 u8 bss_term_dur[12]; 838 char *url = NULL; 839 int ret; 840 u8 nei_rep[1000]; 841 u8 *nei_pos = nei_rep; 842 u8 mbo[10]; 843 size_t mbo_len = 0; 844 845 if (hwaddr_aton(cmd, addr)) { 846 wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 847 return -1; 848 } 849 850 sta = ap_get_sta(hapd, addr); 851 if (sta == NULL) { 852 wpa_printf(MSG_DEBUG, "Station " MACSTR 853 " not found for BSS TM Request message", 854 MAC2STR(addr)); 855 return -1; 856 } 857 858 pos = os_strstr(cmd, " disassoc_timer="); 859 if (pos) { 860 pos += 16; 861 disassoc_timer = atoi(pos); 862 if (disassoc_timer < 0 || disassoc_timer > 65535) { 863 wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); 864 return -1; 865 } 866 } 867 868 pos = os_strstr(cmd, " valid_int="); 869 if (pos) { 870 pos += 11; 871 valid_int = atoi(pos); 872 } 873 874 pos = os_strstr(cmd, " bss_term="); 875 if (pos) { 876 pos += 10; 877 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; 878 /* TODO: TSF configurable/learnable */ 879 bss_term_dur[0] = 4; /* Subelement ID */ 880 bss_term_dur[1] = 10; /* Length */ 881 os_memset(bss_term_dur, 2, 8); 882 end = os_strchr(pos, ','); 883 if (end == NULL) { 884 wpa_printf(MSG_DEBUG, "Invalid bss_term data"); 885 return -1; 886 } 887 end++; 888 WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); 889 } 890 891 892 /* 893 * BSS Transition Candidate List Entries - Neighbor Report elements 894 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>, 895 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>] 896 */ 897 pos = cmd; 898 while (pos) { 899 u8 *nei_start; 900 long int val; 901 char *endptr, *tmp; 902 903 pos = os_strstr(pos, " neighbor="); 904 if (!pos) 905 break; 906 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) { 907 wpa_printf(MSG_DEBUG, 908 "Not enough room for additional neighbor"); 909 return -1; 910 } 911 pos += 10; 912 913 nei_start = nei_pos; 914 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT; 915 nei_pos++; /* length to be filled in */ 916 917 if (hwaddr_aton(pos, nei_pos)) { 918 wpa_printf(MSG_DEBUG, "Invalid BSSID"); 919 return -1; 920 } 921 nei_pos += ETH_ALEN; 922 pos += 17; 923 if (*pos != ',') { 924 wpa_printf(MSG_DEBUG, "Missing BSSID Information"); 925 return -1; 926 } 927 pos++; 928 929 val = strtol(pos, &endptr, 0); 930 WPA_PUT_LE32(nei_pos, val); 931 nei_pos += 4; 932 if (*endptr != ',') { 933 wpa_printf(MSG_DEBUG, "Missing Operating Class"); 934 return -1; 935 } 936 pos = endptr + 1; 937 938 *nei_pos++ = atoi(pos); /* Operating Class */ 939 pos = os_strchr(pos, ','); 940 if (pos == NULL) { 941 wpa_printf(MSG_DEBUG, "Missing Channel Number"); 942 return -1; 943 } 944 pos++; 945 946 *nei_pos++ = atoi(pos); /* Channel Number */ 947 pos = os_strchr(pos, ','); 948 if (pos == NULL) { 949 wpa_printf(MSG_DEBUG, "Missing PHY Type"); 950 return -1; 951 } 952 pos++; 953 954 *nei_pos++ = atoi(pos); /* PHY Type */ 955 end = os_strchr(pos, ' '); 956 tmp = os_strchr(pos, ','); 957 if (tmp && (!end || tmp < end)) { 958 /* Optional Subelements (hexdump) */ 959 size_t len; 960 961 pos = tmp + 1; 962 end = os_strchr(pos, ' '); 963 if (end) 964 len = end - pos; 965 else 966 len = os_strlen(pos); 967 if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) { 968 wpa_printf(MSG_DEBUG, 969 "Not enough room for neighbor subelements"); 970 return -1; 971 } 972 if (len & 0x01 || 973 hexstr2bin(pos, nei_pos, len / 2) < 0) { 974 wpa_printf(MSG_DEBUG, 975 "Invalid neighbor subelement info"); 976 return -1; 977 } 978 nei_pos += len / 2; 979 pos = end; 980 } 981 982 nei_start[1] = nei_pos - nei_start - 2; 983 } 984 985 pos = os_strstr(cmd, " url="); 986 if (pos) { 987 size_t len; 988 pos += 5; 989 end = os_strchr(pos, ' '); 990 if (end) 991 len = end - pos; 992 else 993 len = os_strlen(pos); 994 url = os_malloc(len + 1); 995 if (url == NULL) 996 return -1; 997 os_memcpy(url, pos, len); 998 url[len] = '\0'; 999 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 1000 } 1001 1002 if (os_strstr(cmd, " pref=1")) 1003 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; 1004 if (os_strstr(cmd, " abridged=1")) 1005 req_mode |= WNM_BSS_TM_REQ_ABRIDGED; 1006 if (os_strstr(cmd, " disassoc_imminent=1")) 1007 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 1008 1009 #ifdef CONFIG_MBO 1010 pos = os_strstr(cmd, "mbo="); 1011 if (pos) { 1012 unsigned int mbo_reason, cell_pref, reassoc_delay; 1013 u8 *mbo_pos = mbo; 1014 1015 ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason, 1016 &reassoc_delay, &cell_pref); 1017 if (ret != 3) { 1018 wpa_printf(MSG_DEBUG, 1019 "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>"); 1020 ret = -1; 1021 goto fail; 1022 } 1023 1024 if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) { 1025 wpa_printf(MSG_DEBUG, 1026 "Invalid MBO transition reason code %u", 1027 mbo_reason); 1028 ret = -1; 1029 goto fail; 1030 } 1031 1032 /* Valid values for Cellular preference are: 0, 1, 255 */ 1033 if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) { 1034 wpa_printf(MSG_DEBUG, 1035 "Invalid MBO cellular capability %u", 1036 cell_pref); 1037 ret = -1; 1038 goto fail; 1039 } 1040 1041 if (reassoc_delay > 65535 || 1042 (reassoc_delay && 1043 !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) { 1044 wpa_printf(MSG_DEBUG, 1045 "MBO: Assoc retry delay is only valid in disassoc imminent mode"); 1046 ret = -1; 1047 goto fail; 1048 } 1049 1050 *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON; 1051 *mbo_pos++ = 1; 1052 *mbo_pos++ = mbo_reason; 1053 *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF; 1054 *mbo_pos++ = 1; 1055 *mbo_pos++ = cell_pref; 1056 1057 if (reassoc_delay) { 1058 *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY; 1059 *mbo_pos++ = 2; 1060 WPA_PUT_LE16(mbo_pos, reassoc_delay); 1061 mbo_pos += 2; 1062 } 1063 1064 mbo_len = mbo_pos - mbo; 1065 } 1066 #endif /* CONFIG_MBO */ 1067 1068 ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, 1069 valid_int, bss_term_dur, url, 1070 nei_pos > nei_rep ? nei_rep : NULL, 1071 nei_pos - nei_rep, mbo_len ? mbo : NULL, 1072 mbo_len); 1073 #ifdef CONFIG_MBO 1074 fail: 1075 #endif /* CONFIG_MBO */ 1076 os_free(url); 1077 return ret; 1078 } 1079 1080 #endif /* CONFIG_WNM */ 1081 1082 1083 static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd, 1084 char *buf, size_t buflen) 1085 { 1086 int ret = 0; 1087 char *pos, *end; 1088 1089 pos = buf; 1090 end = buf + buflen; 1091 1092 WPA_ASSERT(hapd->conf->wpa_key_mgmt); 1093 1094 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 1095 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 1096 if (os_snprintf_error(end - pos, ret)) 1097 return pos - buf; 1098 pos += ret; 1099 } 1100 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1101 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 1102 if (os_snprintf_error(end - pos, ret)) 1103 return pos - buf; 1104 pos += ret; 1105 } 1106 #ifdef CONFIG_IEEE80211R_AP 1107 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1108 ret = os_snprintf(pos, end - pos, "FT-PSK "); 1109 if (os_snprintf_error(end - pos, ret)) 1110 return pos - buf; 1111 pos += ret; 1112 } 1113 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1114 ret = os_snprintf(pos, end - pos, "FT-EAP "); 1115 if (os_snprintf_error(end - pos, ret)) 1116 return pos - buf; 1117 pos += ret; 1118 } 1119 #ifdef CONFIG_SAE 1120 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 1121 ret = os_snprintf(pos, end - pos, "FT-SAE "); 1122 if (os_snprintf_error(end - pos, ret)) 1123 return pos - buf; 1124 pos += ret; 1125 } 1126 #endif /* CONFIG_SAE */ 1127 #ifdef CONFIG_FILS 1128 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { 1129 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA256 "); 1130 if (os_snprintf_error(end - pos, ret)) 1131 return pos - buf; 1132 pos += ret; 1133 } 1134 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { 1135 ret = os_snprintf(pos, end - pos, "FT-FILS-SHA384 "); 1136 if (os_snprintf_error(end - pos, ret)) 1137 return pos - buf; 1138 pos += ret; 1139 } 1140 #endif /* CONFIG_FILS */ 1141 #endif /* CONFIG_IEEE80211R_AP */ 1142 #ifdef CONFIG_IEEE80211W 1143 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1144 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 1145 if (os_snprintf_error(end - pos, ret)) 1146 return pos - buf; 1147 pos += ret; 1148 } 1149 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1150 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 1151 if (os_snprintf_error(end - pos, ret)) 1152 return pos - buf; 1153 pos += ret; 1154 } 1155 #endif /* CONFIG_IEEE80211W */ 1156 #ifdef CONFIG_SAE 1157 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 1158 ret = os_snprintf(pos, end - pos, "SAE "); 1159 if (os_snprintf_error(end - pos, ret)) 1160 return pos - buf; 1161 pos += ret; 1162 } 1163 #endif /* CONFIG_SAE */ 1164 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 1165 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); 1166 if (os_snprintf_error(end - pos, ret)) 1167 return pos - buf; 1168 pos += ret; 1169 } 1170 if (hapd->conf->wpa_key_mgmt & 1171 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 1172 ret = os_snprintf(pos, end - pos, 1173 "WPA-EAP-SUITE-B-192 "); 1174 if (os_snprintf_error(end - pos, ret)) 1175 return pos - buf; 1176 pos += ret; 1177 } 1178 #ifdef CONFIG_FILS 1179 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { 1180 ret = os_snprintf(pos, end - pos, "FILS-SHA256 "); 1181 if (os_snprintf_error(end - pos, ret)) 1182 return pos - buf; 1183 pos += ret; 1184 } 1185 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { 1186 ret = os_snprintf(pos, end - pos, "FILS-SHA384 "); 1187 if (os_snprintf_error(end - pos, ret)) 1188 return pos - buf; 1189 pos += ret; 1190 } 1191 #endif /* CONFIG_FILS */ 1192 1193 if (pos > buf && *(pos - 1) == ' ') { 1194 *(pos - 1) = '\0'; 1195 pos--; 1196 } 1197 1198 return pos - buf; 1199 } 1200 1201 1202 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 1203 char *buf, size_t buflen) 1204 { 1205 int ret; 1206 char *pos, *end; 1207 1208 pos = buf; 1209 end = buf + buflen; 1210 1211 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 1212 "ssid=%s\n", 1213 MAC2STR(hapd->own_addr), 1214 wpa_ssid_txt(hapd->conf->ssid.ssid, 1215 hapd->conf->ssid.ssid_len)); 1216 if (os_snprintf_error(end - pos, ret)) 1217 return pos - buf; 1218 pos += ret; 1219 1220 #ifdef CONFIG_WPS 1221 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 1222 hapd->conf->wps_state == 0 ? "disabled" : 1223 (hapd->conf->wps_state == 1 ? "not configured" : 1224 "configured")); 1225 if (os_snprintf_error(end - pos, ret)) 1226 return pos - buf; 1227 pos += ret; 1228 1229 if (hapd->conf->wps_state && hapd->conf->wpa && 1230 hapd->conf->ssid.wpa_passphrase) { 1231 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 1232 hapd->conf->ssid.wpa_passphrase); 1233 if (os_snprintf_error(end - pos, ret)) 1234 return pos - buf; 1235 pos += ret; 1236 } 1237 1238 if (hapd->conf->wps_state && hapd->conf->wpa && 1239 hapd->conf->ssid.wpa_psk && 1240 hapd->conf->ssid.wpa_psk->group) { 1241 char hex[PMK_LEN * 2 + 1]; 1242 wpa_snprintf_hex(hex, sizeof(hex), 1243 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 1244 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 1245 if (os_snprintf_error(end - pos, ret)) 1246 return pos - buf; 1247 pos += ret; 1248 } 1249 #endif /* CONFIG_WPS */ 1250 1251 if (hapd->conf->wpa) { 1252 ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa); 1253 if (os_snprintf_error(end - pos, ret)) 1254 return pos - buf; 1255 pos += ret; 1256 } 1257 1258 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 1259 ret = os_snprintf(pos, end - pos, "key_mgmt="); 1260 if (os_snprintf_error(end - pos, ret)) 1261 return pos - buf; 1262 pos += ret; 1263 1264 pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos); 1265 1266 ret = os_snprintf(pos, end - pos, "\n"); 1267 if (os_snprintf_error(end - pos, ret)) 1268 return pos - buf; 1269 pos += ret; 1270 } 1271 1272 if (hapd->conf->wpa) { 1273 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 1274 wpa_cipher_txt(hapd->conf->wpa_group)); 1275 if (os_snprintf_error(end - pos, ret)) 1276 return pos - buf; 1277 pos += ret; 1278 } 1279 1280 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 1281 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 1282 if (os_snprintf_error(end - pos, ret)) 1283 return pos - buf; 1284 pos += ret; 1285 1286 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 1287 " "); 1288 if (ret < 0) 1289 return pos - buf; 1290 pos += ret; 1291 1292 ret = os_snprintf(pos, end - pos, "\n"); 1293 if (os_snprintf_error(end - pos, ret)) 1294 return pos - buf; 1295 pos += ret; 1296 } 1297 1298 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1299 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1300 if (os_snprintf_error(end - pos, ret)) 1301 return pos - buf; 1302 pos += ret; 1303 1304 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1305 " "); 1306 if (ret < 0) 1307 return pos - buf; 1308 pos += ret; 1309 1310 ret = os_snprintf(pos, end - pos, "\n"); 1311 if (os_snprintf_error(end - pos, ret)) 1312 return pos - buf; 1313 pos += ret; 1314 } 1315 1316 return pos - buf; 1317 } 1318 1319 1320 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1321 { 1322 char *value; 1323 int ret = 0; 1324 1325 value = os_strchr(cmd, ' '); 1326 if (value == NULL) 1327 return -1; 1328 *value++ = '\0'; 1329 1330 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1331 if (0) { 1332 #ifdef CONFIG_WPS_TESTING 1333 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1334 long int val; 1335 val = strtol(value, NULL, 0); 1336 if (val < 0 || val > 0xff) { 1337 ret = -1; 1338 wpa_printf(MSG_DEBUG, "WPS: Invalid " 1339 "wps_version_number %ld", val); 1340 } else { 1341 wps_version_number = val; 1342 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1343 "version %u.%u", 1344 (wps_version_number & 0xf0) >> 4, 1345 wps_version_number & 0x0f); 1346 hostapd_wps_update_ie(hapd); 1347 } 1348 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 1349 wps_testing_dummy_cred = atoi(value); 1350 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 1351 wps_testing_dummy_cred); 1352 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1353 wps_corrupt_pkhash = atoi(value); 1354 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1355 wps_corrupt_pkhash); 1356 #endif /* CONFIG_WPS_TESTING */ 1357 #ifdef CONFIG_TESTING_OPTIONS 1358 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1359 hapd->ext_mgmt_frame_handling = atoi(value); 1360 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 1361 hapd->ext_eapol_frame_io = atoi(value); 1362 #endif /* CONFIG_TESTING_OPTIONS */ 1363 #ifdef CONFIG_MBO 1364 } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) { 1365 int val; 1366 1367 if (!hapd->conf->mbo_enabled) 1368 return -1; 1369 1370 val = atoi(value); 1371 if (val < 0 || val > 1) 1372 return -1; 1373 1374 hapd->mbo_assoc_disallow = val; 1375 ieee802_11_update_beacons(hapd->iface); 1376 1377 /* 1378 * TODO: Need to configure drivers that do AP MLME offload with 1379 * disallowing station logic. 1380 */ 1381 #endif /* CONFIG_MBO */ 1382 } else { 1383 struct sta_info *sta; 1384 struct vlan_description vlan_id; 1385 1386 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1387 if (ret) 1388 return ret; 1389 1390 if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1391 for (sta = hapd->sta_list; sta; sta = sta->next) { 1392 if (hostapd_maclist_found( 1393 hapd->conf->deny_mac, 1394 hapd->conf->num_deny_mac, sta->addr, 1395 &vlan_id) && 1396 (!vlan_id.notempty || 1397 !vlan_compare(&vlan_id, sta->vlan_desc))) 1398 ap_sta_disconnect( 1399 hapd, sta, sta->addr, 1400 WLAN_REASON_UNSPECIFIED); 1401 } 1402 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED && 1403 os_strcasecmp(cmd, "accept_mac_file") == 0) { 1404 for (sta = hapd->sta_list; sta; sta = sta->next) { 1405 if (!hostapd_maclist_found( 1406 hapd->conf->accept_mac, 1407 hapd->conf->num_accept_mac, 1408 sta->addr, &vlan_id) || 1409 (vlan_id.notempty && 1410 vlan_compare(&vlan_id, sta->vlan_desc))) 1411 ap_sta_disconnect( 1412 hapd, sta, sta->addr, 1413 WLAN_REASON_UNSPECIFIED); 1414 } 1415 } 1416 } 1417 1418 return ret; 1419 } 1420 1421 1422 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1423 char *buf, size_t buflen) 1424 { 1425 int res; 1426 1427 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1428 1429 if (os_strcmp(cmd, "version") == 0) { 1430 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1431 if (os_snprintf_error(buflen, res)) 1432 return -1; 1433 return res; 1434 } else if (os_strcmp(cmd, "tls_library") == 0) { 1435 res = tls_get_library_version(buf, buflen); 1436 if (os_snprintf_error(buflen, res)) 1437 return -1; 1438 return res; 1439 } 1440 1441 return -1; 1442 } 1443 1444 1445 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1446 { 1447 if (hostapd_enable_iface(iface) < 0) { 1448 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1449 return -1; 1450 } 1451 return 0; 1452 } 1453 1454 1455 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1456 { 1457 if (hostapd_reload_iface(iface) < 0) { 1458 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1459 return -1; 1460 } 1461 return 0; 1462 } 1463 1464 1465 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1466 { 1467 if (hostapd_disable_iface(iface) < 0) { 1468 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1469 return -1; 1470 } 1471 return 0; 1472 } 1473 1474 1475 #ifdef CONFIG_TESTING_OPTIONS 1476 1477 static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1478 { 1479 union wpa_event_data data; 1480 char *pos, *param; 1481 enum wpa_event_type event; 1482 1483 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1484 1485 os_memset(&data, 0, sizeof(data)); 1486 1487 param = os_strchr(cmd, ' '); 1488 if (param == NULL) 1489 return -1; 1490 *param++ = '\0'; 1491 1492 if (os_strcmp(cmd, "DETECTED") == 0) 1493 event = EVENT_DFS_RADAR_DETECTED; 1494 else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1495 event = EVENT_DFS_CAC_FINISHED; 1496 else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1497 event = EVENT_DFS_CAC_ABORTED; 1498 else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1499 event = EVENT_DFS_NOP_FINISHED; 1500 else { 1501 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1502 cmd); 1503 return -1; 1504 } 1505 1506 pos = os_strstr(param, "freq="); 1507 if (pos) 1508 data.dfs_event.freq = atoi(pos + 5); 1509 1510 pos = os_strstr(param, "ht_enabled=1"); 1511 if (pos) 1512 data.dfs_event.ht_enabled = 1; 1513 1514 pos = os_strstr(param, "chan_offset="); 1515 if (pos) 1516 data.dfs_event.chan_offset = atoi(pos + 12); 1517 1518 pos = os_strstr(param, "chan_width="); 1519 if (pos) 1520 data.dfs_event.chan_width = atoi(pos + 11); 1521 1522 pos = os_strstr(param, "cf1="); 1523 if (pos) 1524 data.dfs_event.cf1 = atoi(pos + 4); 1525 1526 pos = os_strstr(param, "cf2="); 1527 if (pos) 1528 data.dfs_event.cf2 = atoi(pos + 4); 1529 1530 wpa_supplicant_event(hapd, event, &data); 1531 1532 return 0; 1533 } 1534 1535 1536 static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1537 { 1538 size_t len; 1539 u8 *buf; 1540 int res; 1541 1542 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1543 1544 len = os_strlen(cmd); 1545 if (len & 1) 1546 return -1; 1547 len /= 2; 1548 1549 buf = os_malloc(len); 1550 if (buf == NULL) 1551 return -1; 1552 1553 if (hexstr2bin(cmd, buf, len) < 0) { 1554 os_free(buf); 1555 return -1; 1556 } 1557 1558 res = hostapd_drv_send_mlme(hapd, buf, len, 0); 1559 os_free(buf); 1560 return res; 1561 } 1562 1563 1564 static int hostapd_ctrl_iface_mgmt_rx_process(struct hostapd_data *hapd, 1565 char *cmd) 1566 { 1567 char *pos, *param; 1568 size_t len; 1569 u8 *buf; 1570 int freq = 0, datarate = 0, ssi_signal = 0; 1571 union wpa_event_data event; 1572 1573 if (!hapd->ext_mgmt_frame_handling) 1574 return -1; 1575 1576 /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */ 1577 1578 wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd); 1579 1580 pos = cmd; 1581 param = os_strstr(pos, "freq="); 1582 if (param) { 1583 param += 5; 1584 freq = atoi(param); 1585 } 1586 1587 param = os_strstr(pos, " datarate="); 1588 if (param) { 1589 param += 10; 1590 datarate = atoi(param); 1591 } 1592 1593 param = os_strstr(pos, " ssi_signal="); 1594 if (param) { 1595 param += 12; 1596 ssi_signal = atoi(param); 1597 } 1598 1599 param = os_strstr(pos, " frame="); 1600 if (param == NULL) 1601 return -1; 1602 param += 7; 1603 1604 len = os_strlen(param); 1605 if (len & 1) 1606 return -1; 1607 len /= 2; 1608 1609 buf = os_malloc(len); 1610 if (buf == NULL) 1611 return -1; 1612 1613 if (hexstr2bin(param, buf, len) < 0) { 1614 os_free(buf); 1615 return -1; 1616 } 1617 1618 os_memset(&event, 0, sizeof(event)); 1619 event.rx_mgmt.freq = freq; 1620 event.rx_mgmt.frame = buf; 1621 event.rx_mgmt.frame_len = len; 1622 event.rx_mgmt.ssi_signal = ssi_signal; 1623 event.rx_mgmt.datarate = datarate; 1624 hapd->ext_mgmt_frame_handling = 0; 1625 wpa_supplicant_event(hapd, EVENT_RX_MGMT, &event); 1626 hapd->ext_mgmt_frame_handling = 1; 1627 1628 os_free(buf); 1629 1630 return 0; 1631 } 1632 1633 1634 static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd) 1635 { 1636 char *pos; 1637 u8 src[ETH_ALEN], *buf; 1638 int used; 1639 size_t len; 1640 1641 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 1642 1643 pos = cmd; 1644 used = hwaddr_aton2(pos, src); 1645 if (used < 0) 1646 return -1; 1647 pos += used; 1648 while (*pos == ' ') 1649 pos++; 1650 1651 len = os_strlen(pos); 1652 if (len & 1) 1653 return -1; 1654 len /= 2; 1655 1656 buf = os_malloc(len); 1657 if (buf == NULL) 1658 return -1; 1659 1660 if (hexstr2bin(pos, buf, len) < 0) { 1661 os_free(buf); 1662 return -1; 1663 } 1664 1665 ieee802_1x_receive(hapd, src, buf, len); 1666 os_free(buf); 1667 1668 return 0; 1669 } 1670 1671 1672 static u16 ipv4_hdr_checksum(const void *buf, size_t len) 1673 { 1674 size_t i; 1675 u32 sum = 0; 1676 const u16 *pos = buf; 1677 1678 for (i = 0; i < len / 2; i++) 1679 sum += *pos++; 1680 1681 while (sum >> 16) 1682 sum = (sum & 0xffff) + (sum >> 16); 1683 1684 return sum ^ 0xffff; 1685 } 1686 1687 1688 #define HWSIM_PACKETLEN 1500 1689 #define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 1690 1691 static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 1692 size_t len) 1693 { 1694 struct hostapd_data *hapd = ctx; 1695 const struct ether_header *eth; 1696 struct iphdr ip; 1697 const u8 *pos; 1698 unsigned int i; 1699 1700 if (len != HWSIM_PACKETLEN) 1701 return; 1702 1703 eth = (const struct ether_header *) buf; 1704 os_memcpy(&ip, eth + 1, sizeof(ip)); 1705 pos = &buf[sizeof(*eth) + sizeof(ip)]; 1706 1707 if (ip.ihl != 5 || ip.version != 4 || 1708 ntohs(ip.tot_len) != HWSIM_IP_LEN) 1709 return; 1710 1711 for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) { 1712 if (*pos != (u8) i) 1713 return; 1714 pos++; 1715 } 1716 1717 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR, 1718 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost)); 1719 } 1720 1721 1722 static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, 1723 char *cmd) 1724 { 1725 int enabled = atoi(cmd); 1726 char *pos; 1727 const char *ifname; 1728 1729 if (!enabled) { 1730 if (hapd->l2_test) { 1731 l2_packet_deinit(hapd->l2_test); 1732 hapd->l2_test = NULL; 1733 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1734 "test data: Disabled"); 1735 } 1736 return 0; 1737 } 1738 1739 if (hapd->l2_test) 1740 return 0; 1741 1742 pos = os_strstr(cmd, " ifname="); 1743 if (pos) 1744 ifname = pos + 8; 1745 else 1746 ifname = hapd->conf->iface; 1747 1748 hapd->l2_test = l2_packet_init(ifname, hapd->own_addr, 1749 ETHERTYPE_IP, hostapd_data_test_rx, 1750 hapd, 1); 1751 if (hapd->l2_test == NULL) 1752 return -1; 1753 1754 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled"); 1755 1756 return 0; 1757 } 1758 1759 1760 static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) 1761 { 1762 u8 dst[ETH_ALEN], src[ETH_ALEN]; 1763 char *pos; 1764 int used; 1765 long int val; 1766 u8 tos; 1767 u8 buf[2 + HWSIM_PACKETLEN]; 1768 struct ether_header *eth; 1769 struct iphdr *ip; 1770 u8 *dpos; 1771 unsigned int i; 1772 1773 if (hapd->l2_test == NULL) 1774 return -1; 1775 1776 /* format: <dst> <src> <tos> */ 1777 1778 pos = cmd; 1779 used = hwaddr_aton2(pos, dst); 1780 if (used < 0) 1781 return -1; 1782 pos += used; 1783 while (*pos == ' ') 1784 pos++; 1785 used = hwaddr_aton2(pos, src); 1786 if (used < 0) 1787 return -1; 1788 pos += used; 1789 1790 val = strtol(pos, NULL, 0); 1791 if (val < 0 || val > 0xff) 1792 return -1; 1793 tos = val; 1794 1795 eth = (struct ether_header *) &buf[2]; 1796 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 1797 os_memcpy(eth->ether_shost, src, ETH_ALEN); 1798 eth->ether_type = htons(ETHERTYPE_IP); 1799 ip = (struct iphdr *) (eth + 1); 1800 os_memset(ip, 0, sizeof(*ip)); 1801 ip->ihl = 5; 1802 ip->version = 4; 1803 ip->ttl = 64; 1804 ip->tos = tos; 1805 ip->tot_len = htons(HWSIM_IP_LEN); 1806 ip->protocol = 1; 1807 ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); 1808 ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); 1809 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 1810 dpos = (u8 *) (ip + 1); 1811 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) 1812 *dpos++ = i; 1813 1814 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2], 1815 HWSIM_PACKETLEN) < 0) 1816 return -1; 1817 1818 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR 1819 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 1820 1821 return 0; 1822 } 1823 1824 1825 static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd, 1826 char *cmd) 1827 { 1828 u8 *buf; 1829 struct ether_header *eth; 1830 struct l2_packet_data *l2 = NULL; 1831 size_t len; 1832 u16 ethertype; 1833 int res = -1; 1834 const char *ifname = hapd->conf->iface; 1835 1836 if (os_strncmp(cmd, "ifname=", 7) == 0) { 1837 cmd += 7; 1838 ifname = cmd; 1839 cmd = os_strchr(cmd, ' '); 1840 if (cmd == NULL) 1841 return -1; 1842 *cmd++ = '\0'; 1843 } 1844 1845 len = os_strlen(cmd); 1846 if (len & 1 || len < ETH_HLEN * 2) 1847 return -1; 1848 len /= 2; 1849 1850 buf = os_malloc(len); 1851 if (buf == NULL) 1852 return -1; 1853 1854 if (hexstr2bin(cmd, buf, len) < 0) 1855 goto done; 1856 1857 eth = (struct ether_header *) buf; 1858 ethertype = ntohs(eth->ether_type); 1859 1860 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype, 1861 hostapd_data_test_rx, hapd, 1); 1862 if (l2 == NULL) 1863 goto done; 1864 1865 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 1866 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res); 1867 done: 1868 if (l2) 1869 l2_packet_deinit(l2); 1870 os_free(buf); 1871 1872 return res < 0 ? -1 : 0; 1873 } 1874 1875 1876 static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd) 1877 { 1878 #ifdef WPA_TRACE_BFD 1879 char *pos; 1880 1881 wpa_trace_fail_after = atoi(cmd); 1882 pos = os_strchr(cmd, ':'); 1883 if (pos) { 1884 pos++; 1885 os_strlcpy(wpa_trace_fail_func, pos, 1886 sizeof(wpa_trace_fail_func)); 1887 } else { 1888 wpa_trace_fail_after = 0; 1889 } 1890 1891 return 0; 1892 #else /* WPA_TRACE_BFD */ 1893 return -1; 1894 #endif /* WPA_TRACE_BFD */ 1895 } 1896 1897 1898 static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd, 1899 char *buf, size_t buflen) 1900 { 1901 #ifdef WPA_TRACE_BFD 1902 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after, 1903 wpa_trace_fail_func); 1904 #else /* WPA_TRACE_BFD */ 1905 return -1; 1906 #endif /* WPA_TRACE_BFD */ 1907 } 1908 1909 1910 static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd) 1911 { 1912 #ifdef WPA_TRACE_BFD 1913 char *pos; 1914 1915 wpa_trace_test_fail_after = atoi(cmd); 1916 pos = os_strchr(cmd, ':'); 1917 if (pos) { 1918 pos++; 1919 os_strlcpy(wpa_trace_test_fail_func, pos, 1920 sizeof(wpa_trace_test_fail_func)); 1921 } else { 1922 wpa_trace_test_fail_after = 0; 1923 } 1924 1925 return 0; 1926 #else /* WPA_TRACE_BFD */ 1927 return -1; 1928 #endif /* WPA_TRACE_BFD */ 1929 } 1930 1931 1932 static int hostapd_ctrl_get_fail(struct hostapd_data *hapd, 1933 char *buf, size_t buflen) 1934 { 1935 #ifdef WPA_TRACE_BFD 1936 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after, 1937 wpa_trace_test_fail_func); 1938 #else /* WPA_TRACE_BFD */ 1939 return -1; 1940 #endif /* WPA_TRACE_BFD */ 1941 } 1942 1943 #endif /* CONFIG_TESTING_OPTIONS */ 1944 1945 1946 static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 1947 char *pos) 1948 { 1949 #ifdef NEED_AP_MLME 1950 struct csa_settings settings; 1951 int ret; 1952 unsigned int i; 1953 1954 ret = hostapd_parse_csa_settings(pos, &settings); 1955 if (ret) 1956 return ret; 1957 1958 for (i = 0; i < iface->num_bss; i++) { 1959 ret = hostapd_switch_channel(iface->bss[i], &settings); 1960 if (ret) { 1961 /* FIX: What do we do if CSA fails in the middle of 1962 * submitting multi-BSS CSA requests? */ 1963 return ret; 1964 } 1965 } 1966 1967 return 0; 1968 #else /* NEED_AP_MLME */ 1969 return -1; 1970 #endif /* NEED_AP_MLME */ 1971 } 1972 1973 1974 static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 1975 int reply_size, const char *param) 1976 { 1977 #ifdef RADIUS_SERVER 1978 if (os_strcmp(param, "radius_server") == 0) { 1979 return radius_server_get_mib(hapd->radius_srv, reply, 1980 reply_size); 1981 } 1982 #endif /* RADIUS_SERVER */ 1983 return -1; 1984 } 1985 1986 1987 static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 1988 char *buf, size_t buflen) 1989 { 1990 int ret; 1991 char *pos; 1992 u8 *data = NULL; 1993 unsigned int vendor_id, subcmd; 1994 struct wpabuf *reply; 1995 size_t data_len = 0; 1996 1997 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 1998 vendor_id = strtoul(cmd, &pos, 16); 1999 if (!isblank((unsigned char) *pos)) 2000 return -EINVAL; 2001 2002 subcmd = strtoul(pos, &pos, 10); 2003 2004 if (*pos != '\0') { 2005 if (!isblank((unsigned char) *pos++)) 2006 return -EINVAL; 2007 data_len = os_strlen(pos); 2008 } 2009 2010 if (data_len) { 2011 data_len /= 2; 2012 data = os_malloc(data_len); 2013 if (!data) 2014 return -ENOBUFS; 2015 2016 if (hexstr2bin(pos, data, data_len)) { 2017 wpa_printf(MSG_DEBUG, 2018 "Vendor command: wrong parameter format"); 2019 os_free(data); 2020 return -EINVAL; 2021 } 2022 } 2023 2024 reply = wpabuf_alloc((buflen - 1) / 2); 2025 if (!reply) { 2026 os_free(data); 2027 return -ENOBUFS; 2028 } 2029 2030 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 2031 reply); 2032 2033 if (ret == 0) 2034 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 2035 wpabuf_len(reply)); 2036 2037 wpabuf_free(reply); 2038 os_free(data); 2039 2040 return ret; 2041 } 2042 2043 2044 static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd, 2045 const char *cmd) 2046 { 2047 u8 addr[ETH_ALEN]; 2048 struct sta_info *sta; 2049 2050 if (hwaddr_aton(cmd, addr)) 2051 return -1; 2052 2053 sta = ap_get_sta(hapd, addr); 2054 if (!sta || !sta->eapol_sm) 2055 return -1; 2056 2057 eapol_auth_reauthenticate(sta->eapol_sm); 2058 return 0; 2059 } 2060 2061 2062 static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd) 2063 { 2064 u8 addr[ETH_ALEN]; 2065 struct sta_info *sta; 2066 char *pos = cmd, *param; 2067 2068 if (hwaddr_aton(pos, addr) || pos[17] != ' ') 2069 return -1; 2070 pos += 18; 2071 param = pos; 2072 pos = os_strchr(pos, ' '); 2073 if (!pos) 2074 return -1; 2075 *pos++ = '\0'; 2076 2077 sta = ap_get_sta(hapd, addr); 2078 if (!sta || !sta->eapol_sm) 2079 return -1; 2080 2081 return eapol_auth_set_conf(sta->eapol_sm, param, pos); 2082 } 2083 2084 2085 static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd, 2086 char *buf, size_t buflen) 2087 { 2088 char *pos, *end, *stamp; 2089 int ret; 2090 2091 /* cmd: "LOG_LEVEL [<level>]" */ 2092 if (*cmd == '\0') { 2093 pos = buf; 2094 end = buf + buflen; 2095 ret = os_snprintf(pos, end - pos, "Current level: %s\n" 2096 "Timestamp: %d\n", 2097 debug_level_str(wpa_debug_level), 2098 wpa_debug_timestamp); 2099 if (os_snprintf_error(end - pos, ret)) 2100 ret = 0; 2101 2102 return ret; 2103 } 2104 2105 while (*cmd == ' ') 2106 cmd++; 2107 2108 stamp = os_strchr(cmd, ' '); 2109 if (stamp) { 2110 *stamp++ = '\0'; 2111 while (*stamp == ' ') { 2112 stamp++; 2113 } 2114 } 2115 2116 if (os_strlen(cmd)) { 2117 int level = str_to_debug_level(cmd); 2118 if (level < 0) 2119 return -1; 2120 wpa_debug_level = level; 2121 } 2122 2123 if (stamp && os_strlen(stamp)) 2124 wpa_debug_timestamp = atoi(stamp); 2125 2126 os_memcpy(buf, "OK\n", 3); 2127 return 3; 2128 } 2129 2130 2131 #ifdef NEED_AP_MLME 2132 static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd, 2133 char *buf, size_t buflen) 2134 { 2135 struct hostapd_iface *iface = hapd->iface; 2136 char *pos, *end; 2137 struct hostapd_sta_info *info; 2138 struct os_reltime now; 2139 2140 if (!iface->num_sta_seen) 2141 return 0; 2142 2143 sta_track_expire(iface, 0); 2144 2145 pos = buf; 2146 end = buf + buflen; 2147 2148 os_get_reltime(&now); 2149 dl_list_for_each_reverse(info, &iface->sta_seen, 2150 struct hostapd_sta_info, list) { 2151 struct os_reltime age; 2152 int ret; 2153 2154 os_reltime_sub(&now, &info->last_seen, &age); 2155 ret = os_snprintf(pos, end - pos, MACSTR " %u %d\n", 2156 MAC2STR(info->addr), (unsigned int) age.sec, 2157 info->ssi_signal); 2158 if (os_snprintf_error(end - pos, ret)) 2159 break; 2160 pos += ret; 2161 } 2162 2163 return pos - buf; 2164 } 2165 #endif /* NEED_AP_MLME */ 2166 2167 2168 static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd, 2169 const char *cmd) 2170 { 2171 u8 addr[ETH_ALEN]; 2172 2173 if (hwaddr_aton(cmd, addr)) { 2174 wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address"); 2175 return -1; 2176 } 2177 2178 return hostapd_send_lci_req(hapd, addr); 2179 } 2180 2181 2182 static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd) 2183 { 2184 u8 addr[ETH_ALEN]; 2185 char *token, *context = NULL; 2186 int random_interval, min_ap; 2187 u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS]; 2188 unsigned int n_responders; 2189 2190 token = str_token(cmd, " ", &context); 2191 if (!token || hwaddr_aton(token, addr)) { 2192 wpa_printf(MSG_INFO, 2193 "CTRL: REQ_RANGE - Bad destination address"); 2194 return -1; 2195 } 2196 2197 token = str_token(cmd, " ", &context); 2198 if (!token) 2199 return -1; 2200 2201 random_interval = atoi(token); 2202 if (random_interval < 0 || random_interval > 0xffff) 2203 return -1; 2204 2205 token = str_token(cmd, " ", &context); 2206 if (!token) 2207 return -1; 2208 2209 min_ap = atoi(token); 2210 if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP) 2211 return -1; 2212 2213 n_responders = 0; 2214 while ((token = str_token(cmd, " ", &context))) { 2215 if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) { 2216 wpa_printf(MSG_INFO, 2217 "CTRL: REQ_RANGE: Too many responders"); 2218 return -1; 2219 } 2220 2221 if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) { 2222 wpa_printf(MSG_INFO, 2223 "CTRL: REQ_RANGE: Bad responder address"); 2224 return -1; 2225 } 2226 2227 n_responders++; 2228 } 2229 2230 if (!n_responders) { 2231 wpa_printf(MSG_INFO, 2232 "CTRL: REQ_RANGE - No FTM responder address"); 2233 return -1; 2234 } 2235 2236 return hostapd_send_range_req(hapd, addr, random_interval, min_ap, 2237 responders, n_responders); 2238 } 2239 2240 2241 static int hostapd_ctrl_iface_req_beacon(struct hostapd_data *hapd, 2242 const char *cmd, char *reply, 2243 size_t reply_size) 2244 { 2245 u8 addr[ETH_ALEN]; 2246 const char *pos; 2247 struct wpabuf *req; 2248 int ret; 2249 u8 req_mode = 0; 2250 2251 if (hwaddr_aton(cmd, addr)) 2252 return -1; 2253 pos = os_strchr(cmd, ' '); 2254 if (!pos) 2255 return -1; 2256 pos++; 2257 if (os_strncmp(pos, "req_mode=", 9) == 0) { 2258 int val = hex2byte(pos + 9); 2259 2260 if (val < 0) 2261 return -1; 2262 req_mode = val; 2263 pos += 11; 2264 pos = os_strchr(pos, ' '); 2265 if (!pos) 2266 return -1; 2267 pos++; 2268 } 2269 req = wpabuf_parse_bin(pos); 2270 if (!req) 2271 return -1; 2272 2273 ret = hostapd_send_beacon_req(hapd, addr, req_mode, req); 2274 wpabuf_free(req); 2275 if (ret >= 0) 2276 ret = os_snprintf(reply, reply_size, "%d", ret); 2277 return ret; 2278 } 2279 2280 2281 static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf) 2282 { 2283 struct wpa_ssid_value ssid; 2284 u8 bssid[ETH_ALEN]; 2285 struct wpabuf *nr, *lci = NULL, *civic = NULL; 2286 int stationary = 0; 2287 char *tmp; 2288 int ret; 2289 2290 if (!(hapd->conf->radio_measurements[0] & 2291 WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { 2292 wpa_printf(MSG_ERROR, 2293 "CTRL: SET_NEIGHBOR: Neighbor report is not enabled"); 2294 return -1; 2295 } 2296 2297 if (hwaddr_aton(buf, bssid)) { 2298 wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID"); 2299 return -1; 2300 } 2301 2302 tmp = os_strstr(buf, "ssid="); 2303 if (!tmp || ssid_parse(tmp + 5, &ssid)) { 2304 wpa_printf(MSG_ERROR, 2305 "CTRL: SET_NEIGHBOR: Bad or missing SSID"); 2306 return -1; 2307 } 2308 buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' '); 2309 if (!buf) 2310 return -1; 2311 2312 tmp = os_strstr(buf, "nr="); 2313 if (!tmp) { 2314 wpa_printf(MSG_ERROR, 2315 "CTRL: SET_NEIGHBOR: Missing Neighbor Report element"); 2316 return -1; 2317 } 2318 2319 buf = os_strchr(tmp, ' '); 2320 if (buf) 2321 *buf++ = '\0'; 2322 2323 nr = wpabuf_parse_bin(tmp + 3); 2324 if (!nr) { 2325 wpa_printf(MSG_ERROR, 2326 "CTRL: SET_NEIGHBOR: Bad Neighbor Report element"); 2327 return -1; 2328 } 2329 2330 if (!buf) 2331 goto set; 2332 2333 tmp = os_strstr(buf, "lci="); 2334 if (tmp) { 2335 buf = os_strchr(tmp, ' '); 2336 if (buf) 2337 *buf++ = '\0'; 2338 lci = wpabuf_parse_bin(tmp + 4); 2339 if (!lci) { 2340 wpa_printf(MSG_ERROR, 2341 "CTRL: SET_NEIGHBOR: Bad LCI subelement"); 2342 wpabuf_free(nr); 2343 return -1; 2344 } 2345 } 2346 2347 if (!buf) 2348 goto set; 2349 2350 tmp = os_strstr(buf, "civic="); 2351 if (tmp) { 2352 buf = os_strchr(tmp, ' '); 2353 if (buf) 2354 *buf++ = '\0'; 2355 civic = wpabuf_parse_bin(tmp + 6); 2356 if (!civic) { 2357 wpa_printf(MSG_ERROR, 2358 "CTRL: SET_NEIGHBOR: Bad civic subelement"); 2359 wpabuf_free(nr); 2360 wpabuf_free(lci); 2361 return -1; 2362 } 2363 } 2364 2365 if (!buf) 2366 goto set; 2367 2368 if (os_strstr(buf, "stat")) 2369 stationary = 1; 2370 2371 set: 2372 ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic, 2373 stationary); 2374 2375 wpabuf_free(nr); 2376 wpabuf_free(lci); 2377 wpabuf_free(civic); 2378 2379 return ret; 2380 } 2381 2382 2383 static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd, 2384 char *buf) 2385 { 2386 struct wpa_ssid_value ssid; 2387 u8 bssid[ETH_ALEN]; 2388 char *tmp; 2389 2390 if (hwaddr_aton(buf, bssid)) { 2391 wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID"); 2392 return -1; 2393 } 2394 2395 tmp = os_strstr(buf, "ssid="); 2396 if (!tmp || ssid_parse(tmp + 5, &ssid)) { 2397 wpa_printf(MSG_ERROR, 2398 "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID"); 2399 return -1; 2400 } 2401 2402 return hostapd_neighbor_remove(hapd, bssid, &ssid); 2403 } 2404 2405 2406 static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, 2407 size_t buflen) 2408 { 2409 int ret, i; 2410 char *pos, *end; 2411 2412 ret = os_snprintf(buf, buflen, "%016llX:\n", 2413 (long long unsigned) iface->drv_flags); 2414 if (os_snprintf_error(buflen, ret)) 2415 return -1; 2416 2417 pos = buf + ret; 2418 end = buf + buflen; 2419 2420 for (i = 0; i < 64; i++) { 2421 if (iface->drv_flags & (1LLU << i)) { 2422 ret = os_snprintf(pos, end - pos, "%s\n", 2423 driver_flag_to_string(1LLU << i)); 2424 if (os_snprintf_error(end - pos, ret)) 2425 return -1; 2426 pos += ret; 2427 } 2428 } 2429 2430 return pos - buf; 2431 } 2432 2433 2434 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, 2435 char *buf, char *reply, 2436 int reply_size, 2437 struct sockaddr_storage *from, 2438 socklen_t fromlen) 2439 { 2440 int reply_len, res; 2441 2442 os_memcpy(reply, "OK\n", 3); 2443 reply_len = 3; 2444 2445 if (os_strcmp(buf, "PING") == 0) { 2446 os_memcpy(reply, "PONG\n", 5); 2447 reply_len = 5; 2448 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 2449 if (wpa_debug_reopen_file() < 0) 2450 reply_len = -1; 2451 } else if (os_strcmp(buf, "STATUS") == 0) { 2452 reply_len = hostapd_ctrl_iface_status(hapd, reply, 2453 reply_size); 2454 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 2455 reply_len = hostapd_drv_status(hapd, reply, reply_size); 2456 } else if (os_strcmp(buf, "MIB") == 0) { 2457 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 2458 if (reply_len >= 0) { 2459 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 2460 reply_size - reply_len); 2461 if (res < 0) 2462 reply_len = -1; 2463 else 2464 reply_len += res; 2465 } 2466 if (reply_len >= 0) { 2467 res = ieee802_1x_get_mib(hapd, reply + reply_len, 2468 reply_size - reply_len); 2469 if (res < 0) 2470 reply_len = -1; 2471 else 2472 reply_len += res; 2473 } 2474 #ifndef CONFIG_NO_RADIUS 2475 if (reply_len >= 0) { 2476 res = radius_client_get_mib(hapd->radius, 2477 reply + reply_len, 2478 reply_size - reply_len); 2479 if (res < 0) 2480 reply_len = -1; 2481 else 2482 reply_len += res; 2483 } 2484 #endif /* CONFIG_NO_RADIUS */ 2485 } else if (os_strncmp(buf, "MIB ", 4) == 0) { 2486 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 2487 buf + 4); 2488 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 2489 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 2490 reply_size); 2491 } else if (os_strncmp(buf, "STA ", 4) == 0) { 2492 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 2493 reply_size); 2494 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 2495 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 2496 reply_size); 2497 } else if (os_strcmp(buf, "ATTACH") == 0) { 2498 if (hostapd_ctrl_iface_attach(hapd, from, fromlen)) 2499 reply_len = -1; 2500 } else if (os_strcmp(buf, "DETACH") == 0) { 2501 if (hostapd_ctrl_iface_detach(hapd, from, fromlen)) 2502 reply_len = -1; 2503 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 2504 if (hostapd_ctrl_iface_level(hapd, from, fromlen, 2505 buf + 6)) 2506 reply_len = -1; 2507 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 2508 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 2509 reply_len = -1; 2510 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 2511 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 2512 reply_len = -1; 2513 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 2514 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 2515 reply_len = -1; 2516 #ifdef CONFIG_TAXONOMY 2517 } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) { 2518 reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10, 2519 reply, reply_size); 2520 #endif /* CONFIG_TAXONOMY */ 2521 } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) { 2522 if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9)) 2523 reply_len = -1; 2524 } else if (os_strcmp(buf, "STOP_AP") == 0) { 2525 if (hostapd_ctrl_iface_stop_ap(hapd)) 2526 reply_len = -1; 2527 #ifdef CONFIG_IEEE80211W 2528 #ifdef NEED_AP_MLME 2529 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 2530 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 2531 reply_len = -1; 2532 #endif /* NEED_AP_MLME */ 2533 #endif /* CONFIG_IEEE80211W */ 2534 #ifdef CONFIG_WPS 2535 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 2536 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 2537 reply_len = -1; 2538 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 2539 reply_len = hostapd_ctrl_iface_wps_check_pin( 2540 hapd, buf + 14, reply, reply_size); 2541 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 2542 if (hostapd_wps_button_pushed(hapd, NULL)) 2543 reply_len = -1; 2544 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 2545 if (hostapd_wps_cancel(hapd)) 2546 reply_len = -1; 2547 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 2548 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 2549 reply, reply_size); 2550 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 2551 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 2552 reply_len = -1; 2553 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 2554 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 2555 reply_size); 2556 #ifdef CONFIG_WPS_NFC 2557 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 2558 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 2559 reply_len = -1; 2560 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 2561 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 2562 hapd, buf + 21, reply, reply_size); 2563 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 2564 reply_len = hostapd_ctrl_iface_wps_nfc_token( 2565 hapd, buf + 14, reply, reply_size); 2566 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 2567 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 2568 hapd, buf + 21, reply, reply_size); 2569 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 2570 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 2571 reply_len = -1; 2572 #endif /* CONFIG_WPS_NFC */ 2573 #endif /* CONFIG_WPS */ 2574 #ifdef CONFIG_INTERWORKING 2575 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 2576 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 2577 reply_len = -1; 2578 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 2579 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 2580 reply_len = -1; 2581 #endif /* CONFIG_INTERWORKING */ 2582 #ifdef CONFIG_HS20 2583 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 2584 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 2585 reply_len = -1; 2586 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 2587 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 2588 reply_len = -1; 2589 #endif /* CONFIG_HS20 */ 2590 #ifdef CONFIG_WNM 2591 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 2592 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 2593 reply_len = -1; 2594 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 2595 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 2596 reply_len = -1; 2597 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 2598 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) 2599 reply_len = -1; 2600 #endif /* CONFIG_WNM */ 2601 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 2602 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 2603 reply_size); 2604 } else if (os_strncmp(buf, "SET ", 4) == 0) { 2605 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 2606 reply_len = -1; 2607 } else if (os_strncmp(buf, "GET ", 4) == 0) { 2608 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 2609 reply_size); 2610 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 2611 if (hostapd_ctrl_iface_enable(hapd->iface)) 2612 reply_len = -1; 2613 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 2614 if (hostapd_ctrl_iface_reload(hapd->iface)) 2615 reply_len = -1; 2616 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 2617 if (hostapd_ctrl_iface_disable(hapd->iface)) 2618 reply_len = -1; 2619 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 2620 if (ieee802_11_set_beacon(hapd)) 2621 reply_len = -1; 2622 #ifdef CONFIG_TESTING_OPTIONS 2623 } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 2624 if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 2625 reply_len = -1; 2626 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 2627 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 2628 reply_len = -1; 2629 } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) { 2630 if (hostapd_ctrl_iface_mgmt_rx_process(hapd, buf + 16) < 0) 2631 reply_len = -1; 2632 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 2633 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0) 2634 reply_len = -1; 2635 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 2636 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0) 2637 reply_len = -1; 2638 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 2639 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0) 2640 reply_len = -1; 2641 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 2642 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0) 2643 reply_len = -1; 2644 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 2645 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0) 2646 reply_len = -1; 2647 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 2648 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply, 2649 reply_size); 2650 } else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) { 2651 if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0) 2652 reply_len = -1; 2653 } else if (os_strcmp(buf, "GET_FAIL") == 0) { 2654 reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size); 2655 #endif /* CONFIG_TESTING_OPTIONS */ 2656 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 2657 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 2658 reply_len = -1; 2659 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 2660 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 2661 reply_size); 2662 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 2663 ieee802_1x_erp_flush(hapd); 2664 #ifdef RADIUS_SERVER 2665 radius_server_erp_flush(hapd->radius_srv); 2666 #endif /* RADIUS_SERVER */ 2667 } else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) { 2668 if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13)) 2669 reply_len = -1; 2670 } else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) { 2671 if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10)) 2672 reply_len = -1; 2673 } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) { 2674 reply_len = hostapd_ctrl_iface_log_level( 2675 hapd, buf + 9, reply, reply_size); 2676 #ifdef NEED_AP_MLME 2677 } else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) { 2678 reply_len = hostapd_ctrl_iface_track_sta_list( 2679 hapd, reply, reply_size); 2680 #endif /* NEED_AP_MLME */ 2681 } else if (os_strcmp(buf, "PMKSA") == 0) { 2682 reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply, 2683 reply_size); 2684 } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { 2685 hostapd_ctrl_iface_pmksa_flush(hapd); 2686 } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) { 2687 if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13)) 2688 reply_len = -1; 2689 } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) { 2690 if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16)) 2691 reply_len = -1; 2692 } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) { 2693 if (hostapd_ctrl_iface_req_lci(hapd, buf + 8)) 2694 reply_len = -1; 2695 } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) { 2696 if (hostapd_ctrl_iface_req_range(hapd, buf + 10)) 2697 reply_len = -1; 2698 } else if (os_strncmp(buf, "REQ_BEACON ", 11) == 0) { 2699 reply_len = hostapd_ctrl_iface_req_beacon(hapd, buf + 11, 2700 reply, reply_size); 2701 } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { 2702 reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, 2703 reply_size); 2704 } else if (os_strcmp(buf, "TERMINATE") == 0) { 2705 eloop_terminate(); 2706 } else { 2707 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 2708 reply_len = 16; 2709 } 2710 2711 if (reply_len < 0) { 2712 os_memcpy(reply, "FAIL\n", 5); 2713 reply_len = 5; 2714 } 2715 2716 return reply_len; 2717 } 2718 2719 2720 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 2721 void *sock_ctx) 2722 { 2723 struct hostapd_data *hapd = eloop_ctx; 2724 char buf[4096]; 2725 int res; 2726 struct sockaddr_storage from; 2727 socklen_t fromlen = sizeof(from); 2728 char *reply, *pos = buf; 2729 const int reply_size = 4096; 2730 int reply_len; 2731 int level = MSG_DEBUG; 2732 #ifdef CONFIG_CTRL_IFACE_UDP 2733 unsigned char lcookie[COOKIE_LEN]; 2734 #endif /* CONFIG_CTRL_IFACE_UDP */ 2735 2736 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 2737 (struct sockaddr *) &from, &fromlen); 2738 if (res < 0) { 2739 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 2740 strerror(errno)); 2741 return; 2742 } 2743 buf[res] = '\0'; 2744 2745 reply = os_malloc(reply_size); 2746 if (reply == NULL) { 2747 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 2748 fromlen) < 0) { 2749 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2750 strerror(errno)); 2751 } 2752 return; 2753 } 2754 2755 #ifdef CONFIG_CTRL_IFACE_UDP 2756 if (os_strcmp(buf, "GET_COOKIE") == 0) { 2757 os_memcpy(reply, "COOKIE=", 7); 2758 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 2759 cookie, COOKIE_LEN); 2760 reply_len = 7 + 2 * COOKIE_LEN; 2761 goto done; 2762 } 2763 2764 if (os_strncmp(buf, "COOKIE=", 7) != 0 || 2765 hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { 2766 wpa_printf(MSG_DEBUG, 2767 "CTRL: No cookie in the request - drop request"); 2768 os_free(reply); 2769 return; 2770 } 2771 2772 if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) { 2773 wpa_printf(MSG_DEBUG, 2774 "CTRL: Invalid cookie in the request - drop request"); 2775 os_free(reply); 2776 return; 2777 } 2778 2779 pos = buf + 7 + 2 * COOKIE_LEN; 2780 while (*pos == ' ') 2781 pos++; 2782 #endif /* CONFIG_CTRL_IFACE_UDP */ 2783 2784 if (os_strcmp(pos, "PING") == 0) 2785 level = MSG_EXCESSIVE; 2786 wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res); 2787 2788 reply_len = hostapd_ctrl_iface_receive_process(hapd, pos, 2789 reply, reply_size, 2790 &from, fromlen); 2791 2792 #ifdef CONFIG_CTRL_IFACE_UDP 2793 done: 2794 #endif /* CONFIG_CTRL_IFACE_UDP */ 2795 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 2796 fromlen) < 0) { 2797 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2798 strerror(errno)); 2799 } 2800 os_free(reply); 2801 } 2802 2803 2804 #ifndef CONFIG_CTRL_IFACE_UDP 2805 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 2806 { 2807 char *buf; 2808 size_t len; 2809 2810 if (hapd->conf->ctrl_interface == NULL) 2811 return NULL; 2812 2813 len = os_strlen(hapd->conf->ctrl_interface) + 2814 os_strlen(hapd->conf->iface) + 2; 2815 buf = os_malloc(len); 2816 if (buf == NULL) 2817 return NULL; 2818 2819 os_snprintf(buf, len, "%s/%s", 2820 hapd->conf->ctrl_interface, hapd->conf->iface); 2821 buf[len - 1] = '\0'; 2822 return buf; 2823 } 2824 #endif /* CONFIG_CTRL_IFACE_UDP */ 2825 2826 2827 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 2828 enum wpa_msg_type type, 2829 const char *txt, size_t len) 2830 { 2831 struct hostapd_data *hapd = ctx; 2832 if (hapd == NULL) 2833 return; 2834 hostapd_ctrl_iface_send(hapd, level, type, txt, len); 2835 } 2836 2837 2838 int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 2839 { 2840 #ifdef CONFIG_CTRL_IFACE_UDP 2841 int port = HOSTAPD_CTRL_IFACE_PORT; 2842 char p[32] = { 0 }; 2843 char port_str[40], *tmp; 2844 char *pos; 2845 struct addrinfo hints = { 0 }, *res, *saveres; 2846 int n; 2847 2848 if (hapd->ctrl_sock > -1) { 2849 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 2850 return 0; 2851 } 2852 2853 if (hapd->conf->ctrl_interface == NULL) 2854 return 0; 2855 2856 pos = os_strstr(hapd->conf->ctrl_interface, "udp:"); 2857 if (pos) { 2858 pos += 4; 2859 port = atoi(pos); 2860 if (port <= 0) { 2861 wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port"); 2862 goto fail; 2863 } 2864 } 2865 2866 dl_list_init(&hapd->ctrl_dst); 2867 hapd->ctrl_sock = -1; 2868 os_get_random(cookie, COOKIE_LEN); 2869 2870 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 2871 hints.ai_flags = AI_PASSIVE; 2872 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 2873 2874 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 2875 hints.ai_family = AF_INET6; 2876 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 2877 hints.ai_family = AF_INET; 2878 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 2879 hints.ai_socktype = SOCK_DGRAM; 2880 2881 try_again: 2882 os_snprintf(p, sizeof(p), "%d", port); 2883 n = getaddrinfo(NULL, p, &hints, &res); 2884 if (n) { 2885 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 2886 goto fail; 2887 } 2888 2889 saveres = res; 2890 hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype, 2891 res->ai_protocol); 2892 if (hapd->ctrl_sock < 0) { 2893 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 2894 goto fail; 2895 } 2896 2897 if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) { 2898 port--; 2899 if ((HOSTAPD_CTRL_IFACE_PORT - port) < 2900 HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos) 2901 goto try_again; 2902 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 2903 goto fail; 2904 } 2905 2906 freeaddrinfo(saveres); 2907 2908 os_snprintf(port_str, sizeof(port_str), "udp:%d", port); 2909 tmp = os_strdup(port_str); 2910 if (tmp) { 2911 os_free(hapd->conf->ctrl_interface); 2912 hapd->conf->ctrl_interface = tmp; 2913 } 2914 wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port); 2915 2916 if (eloop_register_read_sock(hapd->ctrl_sock, 2917 hostapd_ctrl_iface_receive, hapd, NULL) < 2918 0) { 2919 hostapd_ctrl_iface_deinit(hapd); 2920 return -1; 2921 } 2922 2923 hapd->msg_ctx = hapd; 2924 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 2925 2926 return 0; 2927 2928 fail: 2929 if (hapd->ctrl_sock >= 0) 2930 close(hapd->ctrl_sock); 2931 return -1; 2932 #else /* CONFIG_CTRL_IFACE_UDP */ 2933 struct sockaddr_un addr; 2934 int s = -1; 2935 char *fname = NULL; 2936 2937 if (hapd->ctrl_sock > -1) { 2938 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 2939 return 0; 2940 } 2941 2942 dl_list_init(&hapd->ctrl_dst); 2943 2944 if (hapd->conf->ctrl_interface == NULL) 2945 return 0; 2946 2947 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2948 if (errno == EEXIST) { 2949 wpa_printf(MSG_DEBUG, "Using existing control " 2950 "interface directory."); 2951 } else { 2952 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 2953 strerror(errno)); 2954 goto fail; 2955 } 2956 } 2957 2958 if (hapd->conf->ctrl_interface_gid_set && 2959 chown(hapd->conf->ctrl_interface, -1, 2960 hapd->conf->ctrl_interface_gid) < 0) { 2961 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2962 strerror(errno)); 2963 return -1; 2964 } 2965 2966 if (!hapd->conf->ctrl_interface_gid_set && 2967 hapd->iface->interfaces->ctrl_iface_group && 2968 chown(hapd->conf->ctrl_interface, -1, 2969 hapd->iface->interfaces->ctrl_iface_group) < 0) { 2970 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2971 strerror(errno)); 2972 return -1; 2973 } 2974 2975 #ifdef ANDROID 2976 /* 2977 * Android is using umask 0077 which would leave the control interface 2978 * directory without group access. This breaks things since Wi-Fi 2979 * framework assumes that this directory can be accessed by other 2980 * applications in the wifi group. Fix this by adding group access even 2981 * if umask value would prevent this. 2982 */ 2983 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2984 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 2985 strerror(errno)); 2986 /* Try to continue anyway */ 2987 } 2988 #endif /* ANDROID */ 2989 2990 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 2991 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 2992 goto fail; 2993 2994 s = socket(PF_UNIX, SOCK_DGRAM, 0); 2995 if (s < 0) { 2996 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 2997 goto fail; 2998 } 2999 3000 os_memset(&addr, 0, sizeof(addr)); 3001 #ifdef __FreeBSD__ 3002 addr.sun_len = sizeof(addr); 3003 #endif /* __FreeBSD__ */ 3004 addr.sun_family = AF_UNIX; 3005 fname = hostapd_ctrl_iface_path(hapd); 3006 if (fname == NULL) 3007 goto fail; 3008 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 3009 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3010 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 3011 strerror(errno)); 3012 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3013 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 3014 " allow connections - assuming it was left" 3015 "over from forced program termination"); 3016 if (unlink(fname) < 0) { 3017 wpa_printf(MSG_ERROR, 3018 "Could not unlink existing ctrl_iface socket '%s': %s", 3019 fname, strerror(errno)); 3020 goto fail; 3021 } 3022 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 3023 0) { 3024 wpa_printf(MSG_ERROR, 3025 "hostapd-ctrl-iface: bind(PF_UNIX): %s", 3026 strerror(errno)); 3027 goto fail; 3028 } 3029 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 3030 "ctrl_iface socket '%s'", fname); 3031 } else { 3032 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 3033 "be in use - cannot override it"); 3034 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 3035 "not used anymore", fname); 3036 os_free(fname); 3037 fname = NULL; 3038 goto fail; 3039 } 3040 } 3041 3042 if (hapd->conf->ctrl_interface_gid_set && 3043 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 3044 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 3045 strerror(errno)); 3046 goto fail; 3047 } 3048 3049 if (!hapd->conf->ctrl_interface_gid_set && 3050 hapd->iface->interfaces->ctrl_iface_group && 3051 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 3052 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 3053 strerror(errno)); 3054 goto fail; 3055 } 3056 3057 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 3058 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 3059 strerror(errno)); 3060 goto fail; 3061 } 3062 os_free(fname); 3063 3064 hapd->ctrl_sock = s; 3065 if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 3066 NULL) < 0) { 3067 hostapd_ctrl_iface_deinit(hapd); 3068 return -1; 3069 } 3070 hapd->msg_ctx = hapd; 3071 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 3072 3073 return 0; 3074 3075 fail: 3076 if (s >= 0) 3077 close(s); 3078 if (fname) { 3079 unlink(fname); 3080 os_free(fname); 3081 } 3082 return -1; 3083 #endif /* CONFIG_CTRL_IFACE_UDP */ 3084 } 3085 3086 3087 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 3088 { 3089 struct wpa_ctrl_dst *dst, *prev; 3090 3091 if (hapd->ctrl_sock > -1) { 3092 #ifndef CONFIG_CTRL_IFACE_UDP 3093 char *fname; 3094 #endif /* !CONFIG_CTRL_IFACE_UDP */ 3095 3096 eloop_unregister_read_sock(hapd->ctrl_sock); 3097 close(hapd->ctrl_sock); 3098 hapd->ctrl_sock = -1; 3099 #ifndef CONFIG_CTRL_IFACE_UDP 3100 fname = hostapd_ctrl_iface_path(hapd); 3101 if (fname) 3102 unlink(fname); 3103 os_free(fname); 3104 3105 if (hapd->conf->ctrl_interface && 3106 rmdir(hapd->conf->ctrl_interface) < 0) { 3107 if (errno == ENOTEMPTY) { 3108 wpa_printf(MSG_DEBUG, "Control interface " 3109 "directory not empty - leaving it " 3110 "behind"); 3111 } else { 3112 wpa_printf(MSG_ERROR, 3113 "rmdir[ctrl_interface=%s]: %s", 3114 hapd->conf->ctrl_interface, 3115 strerror(errno)); 3116 } 3117 } 3118 #endif /* !CONFIG_CTRL_IFACE_UDP */ 3119 } 3120 3121 dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst, 3122 list) 3123 os_free(dst); 3124 3125 #ifdef CONFIG_TESTING_OPTIONS 3126 l2_packet_deinit(hapd->l2_test); 3127 hapd->l2_test = NULL; 3128 #endif /* CONFIG_TESTING_OPTIONS */ 3129 } 3130 3131 3132 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 3133 char *buf) 3134 { 3135 if (hostapd_add_iface(interfaces, buf) < 0) { 3136 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 3137 return -1; 3138 } 3139 return 0; 3140 } 3141 3142 3143 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 3144 char *buf) 3145 { 3146 if (hostapd_remove_iface(interfaces, buf) < 0) { 3147 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 3148 return -1; 3149 } 3150 return 0; 3151 } 3152 3153 3154 static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces, 3155 struct sockaddr_storage *from, 3156 socklen_t fromlen) 3157 { 3158 return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen); 3159 } 3160 3161 3162 static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces, 3163 struct sockaddr_storage *from, 3164 socklen_t fromlen) 3165 { 3166 return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen); 3167 } 3168 3169 3170 static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 3171 { 3172 #ifdef CONFIG_WPS_TESTING 3173 wps_version_number = 0x20; 3174 wps_testing_dummy_cred = 0; 3175 wps_corrupt_pkhash = 0; 3176 #endif /* CONFIG_WPS_TESTING */ 3177 } 3178 3179 3180 #ifdef CONFIG_FST 3181 3182 static int 3183 hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces, 3184 const char *cmd) 3185 { 3186 char ifname[IFNAMSIZ + 1]; 3187 struct fst_iface_cfg cfg; 3188 struct hostapd_data *hapd; 3189 struct fst_wpa_obj iface_obj; 3190 3191 if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) { 3192 hapd = hostapd_get_iface(interfaces, ifname); 3193 if (hapd) { 3194 if (hapd->iface->fst) { 3195 wpa_printf(MSG_INFO, "FST: Already attached"); 3196 return -1; 3197 } 3198 fst_hostapd_fill_iface_obj(hapd, &iface_obj); 3199 hapd->iface->fst = fst_attach(ifname, hapd->own_addr, 3200 &iface_obj, &cfg); 3201 if (hapd->iface->fst) 3202 return 0; 3203 } 3204 } 3205 3206 return -EINVAL; 3207 } 3208 3209 3210 static int 3211 hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces, 3212 const char *cmd) 3213 { 3214 char ifname[IFNAMSIZ + 1]; 3215 struct hostapd_data * hapd; 3216 3217 if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) { 3218 hapd = hostapd_get_iface(interfaces, ifname); 3219 if (hapd) { 3220 if (!fst_iface_detach(ifname)) { 3221 hapd->iface->fst = NULL; 3222 hapd->iface->fst_ies = NULL; 3223 return 0; 3224 } 3225 } 3226 } 3227 3228 return -EINVAL; 3229 } 3230 3231 #endif /* CONFIG_FST */ 3232 3233 3234 static struct hostapd_data * 3235 hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces, 3236 const char *ifname) 3237 { 3238 size_t i, j; 3239 3240 for (i = 0; i < interfaces->count; i++) { 3241 struct hostapd_iface *iface = interfaces->iface[i]; 3242 3243 for (j = 0; j < iface->num_bss; j++) { 3244 struct hostapd_data *hapd; 3245 3246 hapd = iface->bss[j]; 3247 if (os_strcmp(ifname, hapd->conf->iface) == 0) 3248 return hapd; 3249 } 3250 } 3251 3252 return NULL; 3253 } 3254 3255 3256 static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd, 3257 struct hostapd_data *dst_hapd, 3258 const char *param) 3259 { 3260 int res; 3261 char *value; 3262 3263 value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 3264 if (!value) { 3265 wpa_printf(MSG_ERROR, 3266 "DUP: cannot allocate buffer to stringify %s", 3267 param); 3268 goto error_return; 3269 } 3270 3271 if (os_strcmp(param, "wpa") == 0) { 3272 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d", 3273 src_hapd->conf->wpa); 3274 } else if (os_strcmp(param, "wpa_key_mgmt") == 0 && 3275 src_hapd->conf->wpa_key_mgmt) { 3276 res = hostapd_ctrl_iface_get_key_mgmt( 3277 src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN); 3278 if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res)) 3279 goto error_stringify; 3280 } else if (os_strcmp(param, "wpa_pairwise") == 0 && 3281 src_hapd->conf->wpa_pairwise) { 3282 res = wpa_write_ciphers(value, 3283 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3284 src_hapd->conf->wpa_pairwise, " "); 3285 if (res < 0) 3286 goto error_stringify; 3287 } else if (os_strcmp(param, "rsn_pairwise") == 0 && 3288 src_hapd->conf->rsn_pairwise) { 3289 res = wpa_write_ciphers(value, 3290 value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3291 src_hapd->conf->rsn_pairwise, " "); 3292 if (res < 0) 3293 goto error_stringify; 3294 } else if (os_strcmp(param, "wpa_passphrase") == 0 && 3295 src_hapd->conf->ssid.wpa_passphrase) { 3296 os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s", 3297 src_hapd->conf->ssid.wpa_passphrase); 3298 } else if (os_strcmp(param, "wpa_psk") == 0 && 3299 src_hapd->conf->ssid.wpa_psk_set) { 3300 wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, 3301 src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 3302 } else { 3303 wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param); 3304 goto error_return; 3305 } 3306 3307 res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value); 3308 os_free(value); 3309 return res; 3310 3311 error_stringify: 3312 wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param); 3313 error_return: 3314 os_free(value); 3315 return -1; 3316 } 3317 3318 3319 static int 3320 hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces, 3321 const char *input, 3322 char *reply, int reply_size) 3323 { 3324 size_t i, j; 3325 int res; 3326 char *pos, *end; 3327 struct hostapd_iface *iface; 3328 int show_ctrl = 0; 3329 3330 if (input) 3331 show_ctrl = !!os_strstr(input, "ctrl"); 3332 3333 pos = reply; 3334 end = reply + reply_size; 3335 3336 for (i = 0; i < interfaces->count; i++) { 3337 iface = interfaces->iface[i]; 3338 3339 for (j = 0; j < iface->num_bss; j++) { 3340 struct hostapd_bss_config *conf; 3341 3342 conf = iface->conf->bss[j]; 3343 if (show_ctrl) 3344 res = os_snprintf(pos, end - pos, 3345 "%s ctrl_iface=%s\n", 3346 conf->iface, 3347 conf->ctrl_interface ? 3348 conf->ctrl_interface : "N/A"); 3349 else 3350 res = os_snprintf(pos, end - pos, "%s\n", 3351 conf->iface); 3352 if (os_snprintf_error(end - pos, res)) { 3353 *pos = '\0'; 3354 return pos - reply; 3355 } 3356 pos += res; 3357 } 3358 } 3359 3360 return pos - reply; 3361 } 3362 3363 3364 static int 3365 hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces, 3366 char *cmd) 3367 { 3368 char *p_start = cmd, *p_end; 3369 struct hostapd_data *src_hapd, *dst_hapd; 3370 3371 /* cmd: "<src ifname> <dst ifname> <variable name> */ 3372 3373 p_end = os_strchr(p_start, ' '); 3374 if (!p_end) { 3375 wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'", 3376 cmd); 3377 return -1; 3378 } 3379 3380 *p_end = '\0'; 3381 src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 3382 if (!src_hapd) { 3383 wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'", 3384 p_start); 3385 return -1; 3386 } 3387 3388 p_start = p_end + 1; 3389 p_end = os_strchr(p_start, ' '); 3390 if (!p_end) { 3391 wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'", 3392 cmd); 3393 return -1; 3394 } 3395 3396 *p_end = '\0'; 3397 dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start); 3398 if (!dst_hapd) { 3399 wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'", 3400 p_start); 3401 return -1; 3402 } 3403 3404 p_start = p_end + 1; 3405 return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start); 3406 } 3407 3408 3409 static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces, 3410 const char *ifname, 3411 char *buf, char *reply, 3412 int reply_size, 3413 struct sockaddr_storage *from, 3414 socklen_t fromlen) 3415 { 3416 struct hostapd_data *hapd; 3417 3418 hapd = hostapd_interfaces_get_hapd(interfaces, ifname); 3419 if (hapd == NULL) { 3420 int res; 3421 3422 res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n"); 3423 if (os_snprintf_error(reply_size, res)) 3424 return -1; 3425 return res; 3426 } 3427 3428 return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size, 3429 from, fromlen); 3430 } 3431 3432 3433 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 3434 void *sock_ctx) 3435 { 3436 void *interfaces = eloop_ctx; 3437 char buffer[256], *buf = buffer; 3438 int res; 3439 struct sockaddr_storage from; 3440 socklen_t fromlen = sizeof(from); 3441 char *reply; 3442 int reply_len; 3443 const int reply_size = 4096; 3444 #ifdef CONFIG_CTRL_IFACE_UDP 3445 unsigned char lcookie[COOKIE_LEN]; 3446 #endif /* CONFIG_CTRL_IFACE_UDP */ 3447 3448 res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, 3449 (struct sockaddr *) &from, &fromlen); 3450 if (res < 0) { 3451 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 3452 strerror(errno)); 3453 return; 3454 } 3455 buf[res] = '\0'; 3456 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 3457 3458 reply = os_malloc(reply_size); 3459 if (reply == NULL) { 3460 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 3461 fromlen) < 0) { 3462 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 3463 strerror(errno)); 3464 } 3465 return; 3466 } 3467 3468 os_memcpy(reply, "OK\n", 3); 3469 reply_len = 3; 3470 3471 #ifdef CONFIG_CTRL_IFACE_UDP 3472 if (os_strcmp(buf, "GET_COOKIE") == 0) { 3473 os_memcpy(reply, "COOKIE=", 7); 3474 wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, 3475 gcookie, COOKIE_LEN); 3476 reply_len = 7 + 2 * COOKIE_LEN; 3477 goto send_reply; 3478 } 3479 3480 if (os_strncmp(buf, "COOKIE=", 7) != 0 || 3481 hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { 3482 wpa_printf(MSG_DEBUG, 3483 "CTRL: No cookie in the request - drop request"); 3484 os_free(reply); 3485 return; 3486 } 3487 3488 if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) { 3489 wpa_printf(MSG_DEBUG, 3490 "CTRL: Invalid cookie in the request - drop request"); 3491 os_free(reply); 3492 return; 3493 } 3494 3495 buf += 7 + 2 * COOKIE_LEN; 3496 while (*buf == ' ') 3497 buf++; 3498 #endif /* CONFIG_CTRL_IFACE_UDP */ 3499 3500 if (os_strncmp(buf, "IFNAME=", 7) == 0) { 3501 char *pos = os_strchr(buf + 7, ' '); 3502 3503 if (pos) { 3504 *pos++ = '\0'; 3505 reply_len = hostapd_global_ctrl_iface_ifname( 3506 interfaces, buf + 7, pos, reply, reply_size, 3507 &from, fromlen); 3508 goto send_reply; 3509 } 3510 } 3511 3512 if (os_strcmp(buf, "PING") == 0) { 3513 os_memcpy(reply, "PONG\n", 5); 3514 reply_len = 5; 3515 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 3516 if (wpa_debug_reopen_file() < 0) 3517 reply_len = -1; 3518 } else if (os_strcmp(buf, "FLUSH") == 0) { 3519 hostapd_ctrl_iface_flush(interfaces); 3520 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 3521 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 3522 reply_len = -1; 3523 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 3524 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 3525 reply_len = -1; 3526 } else if (os_strcmp(buf, "ATTACH") == 0) { 3527 if (hostapd_global_ctrl_iface_attach(interfaces, &from, 3528 fromlen)) 3529 reply_len = -1; 3530 } else if (os_strcmp(buf, "DETACH") == 0) { 3531 if (hostapd_global_ctrl_iface_detach(interfaces, &from, 3532 fromlen)) 3533 reply_len = -1; 3534 #ifdef CONFIG_MODULE_TESTS 3535 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 3536 if (hapd_module_tests() < 0) 3537 reply_len = -1; 3538 #endif /* CONFIG_MODULE_TESTS */ 3539 #ifdef CONFIG_FST 3540 } else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) { 3541 if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11)) 3542 reply_len = os_snprintf(reply, reply_size, "OK\n"); 3543 else 3544 reply_len = -1; 3545 } else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) { 3546 if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11)) 3547 reply_len = os_snprintf(reply, reply_size, "OK\n"); 3548 else 3549 reply_len = -1; 3550 } else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) { 3551 reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size); 3552 #endif /* CONFIG_FST */ 3553 } else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) { 3554 if (!hostapd_global_ctrl_iface_dup_network(interfaces, 3555 buf + 12)) 3556 reply_len = os_snprintf(reply, reply_size, "OK\n"); 3557 else 3558 reply_len = -1; 3559 } else if (os_strncmp(buf, "INTERFACES", 10) == 0) { 3560 reply_len = hostapd_global_ctrl_iface_interfaces( 3561 interfaces, buf + 10, reply, sizeof(buffer)); 3562 } else if (os_strcmp(buf, "TERMINATE") == 0) { 3563 eloop_terminate(); 3564 } else { 3565 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 3566 "ignored"); 3567 reply_len = -1; 3568 } 3569 3570 send_reply: 3571 if (reply_len < 0) { 3572 os_memcpy(reply, "FAIL\n", 5); 3573 reply_len = 5; 3574 } 3575 3576 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 3577 fromlen) < 0) { 3578 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 3579 strerror(errno)); 3580 } 3581 os_free(reply); 3582 } 3583 3584 3585 #ifndef CONFIG_CTRL_IFACE_UDP 3586 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 3587 { 3588 char *buf; 3589 size_t len; 3590 3591 if (interface->global_iface_path == NULL) 3592 return NULL; 3593 3594 len = os_strlen(interface->global_iface_path) + 3595 os_strlen(interface->global_iface_name) + 2; 3596 buf = os_malloc(len); 3597 if (buf == NULL) 3598 return NULL; 3599 3600 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 3601 interface->global_iface_name); 3602 buf[len - 1] = '\0'; 3603 return buf; 3604 } 3605 #endif /* CONFIG_CTRL_IFACE_UDP */ 3606 3607 3608 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 3609 { 3610 #ifdef CONFIG_CTRL_IFACE_UDP 3611 int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT; 3612 char p[32] = { 0 }; 3613 char *pos; 3614 struct addrinfo hints = { 0 }, *res, *saveres; 3615 int n; 3616 3617 if (interface->global_ctrl_sock > -1) { 3618 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 3619 return 0; 3620 } 3621 3622 if (interface->global_iface_path == NULL) 3623 return 0; 3624 3625 pos = os_strstr(interface->global_iface_path, "udp:"); 3626 if (pos) { 3627 pos += 4; 3628 port = atoi(pos); 3629 if (port <= 0) { 3630 wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port"); 3631 goto fail; 3632 } 3633 } 3634 3635 os_get_random(gcookie, COOKIE_LEN); 3636 3637 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 3638 hints.ai_flags = AI_PASSIVE; 3639 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 3640 3641 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 3642 hints.ai_family = AF_INET6; 3643 #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 3644 hints.ai_family = AF_INET; 3645 #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ 3646 hints.ai_socktype = SOCK_DGRAM; 3647 3648 try_again: 3649 os_snprintf(p, sizeof(p), "%d", port); 3650 n = getaddrinfo(NULL, p, &hints, &res); 3651 if (n) { 3652 wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n)); 3653 goto fail; 3654 } 3655 3656 saveres = res; 3657 interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype, 3658 res->ai_protocol); 3659 if (interface->global_ctrl_sock < 0) { 3660 wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno)); 3661 goto fail; 3662 } 3663 3664 if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) < 3665 0) { 3666 port++; 3667 if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) < 3668 HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos) 3669 goto try_again; 3670 wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno)); 3671 goto fail; 3672 } 3673 3674 freeaddrinfo(saveres); 3675 3676 wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port); 3677 3678 if (eloop_register_read_sock(interface->global_ctrl_sock, 3679 hostapd_global_ctrl_iface_receive, 3680 interface, NULL) < 0) { 3681 hostapd_global_ctrl_iface_deinit(interface); 3682 return -1; 3683 } 3684 3685 return 0; 3686 3687 fail: 3688 if (interface->global_ctrl_sock >= 0) 3689 close(interface->global_ctrl_sock); 3690 return -1; 3691 #else /* CONFIG_CTRL_IFACE_UDP */ 3692 struct sockaddr_un addr; 3693 int s = -1; 3694 char *fname = NULL; 3695 3696 if (interface->global_iface_path == NULL) { 3697 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 3698 return 0; 3699 } 3700 3701 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 3702 if (errno == EEXIST) { 3703 wpa_printf(MSG_DEBUG, "Using existing control " 3704 "interface directory."); 3705 } else { 3706 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 3707 strerror(errno)); 3708 goto fail; 3709 } 3710 } else if (interface->ctrl_iface_group && 3711 chown(interface->global_iface_path, -1, 3712 interface->ctrl_iface_group) < 0) { 3713 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 3714 strerror(errno)); 3715 goto fail; 3716 } 3717 3718 if (os_strlen(interface->global_iface_path) + 1 + 3719 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 3720 goto fail; 3721 3722 s = socket(PF_UNIX, SOCK_DGRAM, 0); 3723 if (s < 0) { 3724 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 3725 goto fail; 3726 } 3727 3728 os_memset(&addr, 0, sizeof(addr)); 3729 #ifdef __FreeBSD__ 3730 addr.sun_len = sizeof(addr); 3731 #endif /* __FreeBSD__ */ 3732 addr.sun_family = AF_UNIX; 3733 fname = hostapd_global_ctrl_iface_path(interface); 3734 if (fname == NULL) 3735 goto fail; 3736 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 3737 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3738 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 3739 strerror(errno)); 3740 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 3741 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 3742 " allow connections - assuming it was left" 3743 "over from forced program termination"); 3744 if (unlink(fname) < 0) { 3745 wpa_printf(MSG_ERROR, 3746 "Could not unlink existing ctrl_iface socket '%s': %s", 3747 fname, strerror(errno)); 3748 goto fail; 3749 } 3750 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 3751 0) { 3752 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s", 3753 strerror(errno)); 3754 goto fail; 3755 } 3756 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 3757 "ctrl_iface socket '%s'", fname); 3758 } else { 3759 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 3760 "be in use - cannot override it"); 3761 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 3762 "not used anymore", fname); 3763 os_free(fname); 3764 fname = NULL; 3765 goto fail; 3766 } 3767 } 3768 3769 if (interface->ctrl_iface_group && 3770 chown(fname, -1, interface->ctrl_iface_group) < 0) { 3771 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 3772 strerror(errno)); 3773 goto fail; 3774 } 3775 3776 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 3777 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 3778 strerror(errno)); 3779 goto fail; 3780 } 3781 os_free(fname); 3782 3783 interface->global_ctrl_sock = s; 3784 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 3785 interface, NULL); 3786 3787 return 0; 3788 3789 fail: 3790 if (s >= 0) 3791 close(s); 3792 if (fname) { 3793 unlink(fname); 3794 os_free(fname); 3795 } 3796 return -1; 3797 #endif /* CONFIG_CTRL_IFACE_UDP */ 3798 } 3799 3800 3801 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 3802 { 3803 #ifndef CONFIG_CTRL_IFACE_UDP 3804 char *fname = NULL; 3805 #endif /* CONFIG_CTRL_IFACE_UDP */ 3806 struct wpa_ctrl_dst *dst, *prev; 3807 3808 if (interfaces->global_ctrl_sock > -1) { 3809 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 3810 close(interfaces->global_ctrl_sock); 3811 interfaces->global_ctrl_sock = -1; 3812 #ifndef CONFIG_CTRL_IFACE_UDP 3813 fname = hostapd_global_ctrl_iface_path(interfaces); 3814 if (fname) { 3815 unlink(fname); 3816 os_free(fname); 3817 } 3818 3819 if (interfaces->global_iface_path && 3820 rmdir(interfaces->global_iface_path) < 0) { 3821 if (errno == ENOTEMPTY) { 3822 wpa_printf(MSG_DEBUG, "Control interface " 3823 "directory not empty - leaving it " 3824 "behind"); 3825 } else { 3826 wpa_printf(MSG_ERROR, 3827 "rmdir[ctrl_interface=%s]: %s", 3828 interfaces->global_iface_path, 3829 strerror(errno)); 3830 } 3831 } 3832 #endif /* CONFIG_CTRL_IFACE_UDP */ 3833 } 3834 3835 os_free(interfaces->global_iface_path); 3836 interfaces->global_iface_path = NULL; 3837 3838 dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst, 3839 struct wpa_ctrl_dst, list) 3840 os_free(dst); 3841 } 3842 3843 3844 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 3845 enum wpa_msg_type type, 3846 const char *buf, size_t len) 3847 { 3848 struct wpa_ctrl_dst *dst, *next; 3849 struct dl_list *ctrl_dst; 3850 struct msghdr msg; 3851 int idx; 3852 struct iovec io[2]; 3853 char levelstr[10]; 3854 int s; 3855 3856 if (type != WPA_MSG_ONLY_GLOBAL) { 3857 s = hapd->ctrl_sock; 3858 ctrl_dst = &hapd->ctrl_dst; 3859 } else { 3860 s = hapd->iface->interfaces->global_ctrl_sock; 3861 ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst; 3862 } 3863 3864 if (s < 0 || dl_list_empty(ctrl_dst)) 3865 return; 3866 3867 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 3868 io[0].iov_base = levelstr; 3869 io[0].iov_len = os_strlen(levelstr); 3870 io[1].iov_base = (char *) buf; 3871 io[1].iov_len = len; 3872 os_memset(&msg, 0, sizeof(msg)); 3873 msg.msg_iov = io; 3874 msg.msg_iovlen = 2; 3875 3876 idx = 0; 3877 dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) { 3878 if (level >= dst->debug_level) { 3879 sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send", 3880 &dst->addr, dst->addrlen); 3881 msg.msg_name = &dst->addr; 3882 msg.msg_namelen = dst->addrlen; 3883 if (sendmsg(s, &msg, 0) < 0) { 3884 int _errno = errno; 3885 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 3886 "%d - %s", 3887 idx, errno, strerror(errno)); 3888 dst->errors++; 3889 if (dst->errors > 10 || _errno == ENOENT) { 3890 if (type != WPA_MSG_ONLY_GLOBAL) 3891 hostapd_ctrl_iface_detach( 3892 hapd, &dst->addr, 3893 dst->addrlen); 3894 else 3895 hostapd_global_ctrl_iface_detach( 3896 hapd->iface->interfaces, 3897 &dst->addr, 3898 dst->addrlen); 3899 } 3900 } else 3901 dst->errors = 0; 3902 } 3903 idx++; 3904 } 3905 } 3906 3907 #endif /* CONFIG_NATIVE_WINDOWS */ 3908