1/* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "utils/includes.h" 10 11#ifndef CONFIG_NATIVE_WINDOWS 12 13#ifdef CONFIG_TESTING_OPTIONS 14#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#include "utils/common.h" 23#include "utils/eloop.h" 24#include "common/version.h" 25#include "common/ieee802_11_defs.h" 26#include "crypto/tls.h" 27#include "drivers/driver.h" 28#include "radius/radius_client.h" 29#include "radius/radius_server.h" 30#include "l2_packet/l2_packet.h" 31#include "ap/hostapd.h" 32#include "ap/ap_config.h" 33#include "ap/ieee802_1x.h" 34#include "ap/wpa_auth.h" 35#include "ap/ieee802_11.h" 36#include "ap/sta_info.h" 37#include "ap/wps_hostapd.h" 38#include "ap/ctrl_iface_ap.h" 39#include "ap/ap_drv_ops.h" 40#include "ap/hs20.h" 41#include "ap/wnm_ap.h" 42#include "ap/wpa_auth.h" 43#include "ap/beacon.h" 44#include "wps/wps_defs.h" 45#include "wps/wps.h" 46#include "config_file.h" 47#include "ctrl_iface.h" 48 49 50struct wpa_ctrl_dst { 51 struct wpa_ctrl_dst *next; 52 struct sockaddr_un addr; 53 socklen_t addrlen; 54 int debug_level; 55 int errors; 56}; 57 58 59static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 60 enum wpa_msg_type type, 61 const char *buf, size_t len); 62 63 64static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 65 struct sockaddr_un *from, 66 socklen_t fromlen) 67{ 68 struct wpa_ctrl_dst *dst; 69 70 dst = os_zalloc(sizeof(*dst)); 71 if (dst == NULL) 72 return -1; 73 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 74 dst->addrlen = fromlen; 75 dst->debug_level = MSG_INFO; 76 dst->next = hapd->ctrl_dst; 77 hapd->ctrl_dst = dst; 78 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 79 (u8 *) from->sun_path, 80 fromlen - offsetof(struct sockaddr_un, sun_path)); 81 return 0; 82} 83 84 85static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 86 struct sockaddr_un *from, 87 socklen_t fromlen) 88{ 89 struct wpa_ctrl_dst *dst, *prev = NULL; 90 91 dst = hapd->ctrl_dst; 92 while (dst) { 93 if (fromlen == dst->addrlen && 94 os_memcmp(from->sun_path, dst->addr.sun_path, 95 fromlen - offsetof(struct sockaddr_un, sun_path)) 96 == 0) { 97 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 98 (u8 *) from->sun_path, 99 fromlen - 100 offsetof(struct sockaddr_un, sun_path)); 101 if (prev == NULL) 102 hapd->ctrl_dst = dst->next; 103 else 104 prev->next = dst->next; 105 os_free(dst); 106 return 0; 107 } 108 prev = dst; 109 dst = dst->next; 110 } 111 return -1; 112} 113 114 115static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 116 struct sockaddr_un *from, 117 socklen_t fromlen, 118 char *level) 119{ 120 struct wpa_ctrl_dst *dst; 121 122 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 123 124 dst = hapd->ctrl_dst; 125 while (dst) { 126 if (fromlen == dst->addrlen && 127 os_memcmp(from->sun_path, dst->addr.sun_path, 128 fromlen - offsetof(struct sockaddr_un, sun_path)) 129 == 0) { 130 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 131 "level", (u8 *) from->sun_path, fromlen - 132 offsetof(struct sockaddr_un, sun_path)); 133 dst->debug_level = atoi(level); 134 return 0; 135 } 136 dst = dst->next; 137 } 138 139 return -1; 140} 141 142 143static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 144 const char *txtaddr) 145{ 146 u8 addr[ETH_ALEN]; 147 struct sta_info *sta; 148 149 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 150 151 if (hwaddr_aton(txtaddr, addr)) 152 return -1; 153 154 sta = ap_get_sta(hapd, addr); 155 if (sta) 156 return 0; 157 158 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 159 "notification", MAC2STR(addr)); 160 sta = ap_sta_add(hapd, addr); 161 if (sta == NULL) 162 return -1; 163 164 hostapd_new_assoc_sta(hapd, sta, 0); 165 return 0; 166} 167 168 169#ifdef CONFIG_IEEE80211W 170#ifdef NEED_AP_MLME 171static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 172 const char *txtaddr) 173{ 174 u8 addr[ETH_ALEN]; 175 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 176 177 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 178 179 if (hwaddr_aton(txtaddr, addr) || 180 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 181 return -1; 182 183 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 184 185 return 0; 186} 187#endif /* NEED_AP_MLME */ 188#endif /* CONFIG_IEEE80211W */ 189 190 191#ifdef CONFIG_WPS 192static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 193{ 194 char *pin = os_strchr(txt, ' '); 195 char *timeout_txt; 196 int timeout; 197 u8 addr_buf[ETH_ALEN], *addr = NULL; 198 char *pos; 199 200 if (pin == NULL) 201 return -1; 202 *pin++ = '\0'; 203 204 timeout_txt = os_strchr(pin, ' '); 205 if (timeout_txt) { 206 *timeout_txt++ = '\0'; 207 timeout = atoi(timeout_txt); 208 pos = os_strchr(timeout_txt, ' '); 209 if (pos) { 210 *pos++ = '\0'; 211 if (hwaddr_aton(pos, addr_buf) == 0) 212 addr = addr_buf; 213 } 214 } else 215 timeout = 0; 216 217 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 218} 219 220 221static int hostapd_ctrl_iface_wps_check_pin( 222 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 223{ 224 char pin[9]; 225 size_t len; 226 char *pos; 227 int ret; 228 229 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 230 (u8 *) cmd, os_strlen(cmd)); 231 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 232 if (*pos < '0' || *pos > '9') 233 continue; 234 pin[len++] = *pos; 235 if (len == 9) { 236 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 237 return -1; 238 } 239 } 240 if (len != 4 && len != 8) { 241 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 242 return -1; 243 } 244 pin[len] = '\0'; 245 246 if (len == 8) { 247 unsigned int pin_val; 248 pin_val = atoi(pin); 249 if (!wps_pin_valid(pin_val)) { 250 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 251 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 252 if (os_snprintf_error(buflen, ret)) 253 return -1; 254 return ret; 255 } 256 } 257 258 ret = os_snprintf(buf, buflen, "%s", pin); 259 if (os_snprintf_error(buflen, ret)) 260 return -1; 261 262 return ret; 263} 264 265 266#ifdef CONFIG_WPS_NFC 267static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 268 char *pos) 269{ 270 size_t len; 271 struct wpabuf *buf; 272 int ret; 273 274 len = os_strlen(pos); 275 if (len & 0x01) 276 return -1; 277 len /= 2; 278 279 buf = wpabuf_alloc(len); 280 if (buf == NULL) 281 return -1; 282 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 283 wpabuf_free(buf); 284 return -1; 285 } 286 287 ret = hostapd_wps_nfc_tag_read(hapd, buf); 288 wpabuf_free(buf); 289 290 return ret; 291} 292 293 294static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 295 char *cmd, char *reply, 296 size_t max_len) 297{ 298 int ndef; 299 struct wpabuf *buf; 300 int res; 301 302 if (os_strcmp(cmd, "WPS") == 0) 303 ndef = 0; 304 else if (os_strcmp(cmd, "NDEF") == 0) 305 ndef = 1; 306 else 307 return -1; 308 309 buf = hostapd_wps_nfc_config_token(hapd, ndef); 310 if (buf == NULL) 311 return -1; 312 313 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 314 wpabuf_len(buf)); 315 reply[res++] = '\n'; 316 reply[res] = '\0'; 317 318 wpabuf_free(buf); 319 320 return res; 321} 322 323 324static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 325 char *reply, size_t max_len, 326 int ndef) 327{ 328 struct wpabuf *buf; 329 int res; 330 331 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 332 if (buf == NULL) 333 return -1; 334 335 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 336 wpabuf_len(buf)); 337 reply[res++] = '\n'; 338 reply[res] = '\0'; 339 340 wpabuf_free(buf); 341 342 return res; 343} 344 345 346static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 347 char *cmd, char *reply, 348 size_t max_len) 349{ 350 if (os_strcmp(cmd, "WPS") == 0) 351 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 352 max_len, 0); 353 354 if (os_strcmp(cmd, "NDEF") == 0) 355 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 356 max_len, 1); 357 358 if (os_strcmp(cmd, "enable") == 0) 359 return hostapd_wps_nfc_token_enable(hapd); 360 361 if (os_strcmp(cmd, "disable") == 0) { 362 hostapd_wps_nfc_token_disable(hapd); 363 return 0; 364 } 365 366 return -1; 367} 368 369 370static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 371 char *cmd, char *reply, 372 size_t max_len) 373{ 374 struct wpabuf *buf; 375 int res; 376 char *pos; 377 int ndef; 378 379 pos = os_strchr(cmd, ' '); 380 if (pos == NULL) 381 return -1; 382 *pos++ = '\0'; 383 384 if (os_strcmp(cmd, "WPS") == 0) 385 ndef = 0; 386 else if (os_strcmp(cmd, "NDEF") == 0) 387 ndef = 1; 388 else 389 return -1; 390 391 if (os_strcmp(pos, "WPS-CR") == 0) 392 buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 393 else 394 buf = NULL; 395 if (buf == NULL) 396 return -1; 397 398 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 399 wpabuf_len(buf)); 400 reply[res++] = '\n'; 401 reply[res] = '\0'; 402 403 wpabuf_free(buf); 404 405 return res; 406} 407 408 409static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 410 char *cmd) 411{ 412 size_t len; 413 struct wpabuf *req, *sel; 414 int ret; 415 char *pos, *role, *type, *pos2; 416 417 role = cmd; 418 pos = os_strchr(role, ' '); 419 if (pos == NULL) 420 return -1; 421 *pos++ = '\0'; 422 423 type = pos; 424 pos = os_strchr(type, ' '); 425 if (pos == NULL) 426 return -1; 427 *pos++ = '\0'; 428 429 pos2 = os_strchr(pos, ' '); 430 if (pos2 == NULL) 431 return -1; 432 *pos2++ = '\0'; 433 434 len = os_strlen(pos); 435 if (len & 0x01) 436 return -1; 437 len /= 2; 438 439 req = wpabuf_alloc(len); 440 if (req == NULL) 441 return -1; 442 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 443 wpabuf_free(req); 444 return -1; 445 } 446 447 len = os_strlen(pos2); 448 if (len & 0x01) { 449 wpabuf_free(req); 450 return -1; 451 } 452 len /= 2; 453 454 sel = wpabuf_alloc(len); 455 if (sel == NULL) { 456 wpabuf_free(req); 457 return -1; 458 } 459 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 460 wpabuf_free(req); 461 wpabuf_free(sel); 462 return -1; 463 } 464 465 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 466 ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 467 } else { 468 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 469 "reported: role=%s type=%s", role, type); 470 ret = -1; 471 } 472 wpabuf_free(req); 473 wpabuf_free(sel); 474 475 return ret; 476} 477 478#endif /* CONFIG_WPS_NFC */ 479 480 481static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 482 char *buf, size_t buflen) 483{ 484 int timeout = 300; 485 char *pos; 486 const char *pin_txt; 487 488 pos = os_strchr(txt, ' '); 489 if (pos) 490 *pos++ = '\0'; 491 492 if (os_strcmp(txt, "disable") == 0) { 493 hostapd_wps_ap_pin_disable(hapd); 494 return os_snprintf(buf, buflen, "OK\n"); 495 } 496 497 if (os_strcmp(txt, "random") == 0) { 498 if (pos) 499 timeout = atoi(pos); 500 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 501 if (pin_txt == NULL) 502 return -1; 503 return os_snprintf(buf, buflen, "%s", pin_txt); 504 } 505 506 if (os_strcmp(txt, "get") == 0) { 507 pin_txt = hostapd_wps_ap_pin_get(hapd); 508 if (pin_txt == NULL) 509 return -1; 510 return os_snprintf(buf, buflen, "%s", pin_txt); 511 } 512 513 if (os_strcmp(txt, "set") == 0) { 514 char *pin; 515 if (pos == NULL) 516 return -1; 517 pin = pos; 518 pos = os_strchr(pos, ' '); 519 if (pos) { 520 *pos++ = '\0'; 521 timeout = atoi(pos); 522 } 523 if (os_strlen(pin) > buflen) 524 return -1; 525 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 526 return -1; 527 return os_snprintf(buf, buflen, "%s", pin); 528 } 529 530 return -1; 531} 532 533 534static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 535{ 536 char *pos; 537 char *ssid, *auth, *encr = NULL, *key = NULL; 538 539 ssid = txt; 540 pos = os_strchr(txt, ' '); 541 if (!pos) 542 return -1; 543 *pos++ = '\0'; 544 545 auth = pos; 546 pos = os_strchr(pos, ' '); 547 if (pos) { 548 *pos++ = '\0'; 549 encr = pos; 550 pos = os_strchr(pos, ' '); 551 if (pos) { 552 *pos++ = '\0'; 553 key = pos; 554 } 555 } 556 557 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 558} 559 560 561static const char * pbc_status_str(enum pbc_status status) 562{ 563 switch (status) { 564 case WPS_PBC_STATUS_DISABLE: 565 return "Disabled"; 566 case WPS_PBC_STATUS_ACTIVE: 567 return "Active"; 568 case WPS_PBC_STATUS_TIMEOUT: 569 return "Timed-out"; 570 case WPS_PBC_STATUS_OVERLAP: 571 return "Overlap"; 572 default: 573 return "Unknown"; 574 } 575} 576 577 578static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, 579 char *buf, size_t buflen) 580{ 581 int ret; 582 char *pos, *end; 583 584 pos = buf; 585 end = buf + buflen; 586 587 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", 588 pbc_status_str(hapd->wps_stats.pbc_status)); 589 590 if (os_snprintf_error(end - pos, ret)) 591 return pos - buf; 592 pos += ret; 593 594 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 595 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 596 "Success": 597 (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 598 "Failed" : "None"))); 599 600 if (os_snprintf_error(end - pos, ret)) 601 return pos - buf; 602 pos += ret; 603 604 /* If status == Failure - Add possible Reasons */ 605 if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 606 hapd->wps_stats.failure_reason > 0) { 607 ret = os_snprintf(pos, end - pos, 608 "Failure Reason: %s\n", 609 wps_ei_str(hapd->wps_stats.failure_reason)); 610 611 if (os_snprintf_error(end - pos, ret)) 612 return pos - buf; 613 pos += ret; 614 } 615 616 if (hapd->wps_stats.status) { 617 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 618 MAC2STR(hapd->wps_stats.peer_addr)); 619 620 if (os_snprintf_error(end - pos, ret)) 621 return pos - buf; 622 pos += ret; 623 } 624 625 return pos - buf; 626} 627 628#endif /* CONFIG_WPS */ 629 630#ifdef CONFIG_HS20 631 632static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 633 const char *cmd) 634{ 635 u8 addr[ETH_ALEN]; 636 const char *url; 637 638 if (hwaddr_aton(cmd, addr)) 639 return -1; 640 url = cmd + 17; 641 if (*url == '\0') { 642 url = NULL; 643 } else { 644 if (*url != ' ') 645 return -1; 646 url++; 647 if (*url == '\0') 648 url = NULL; 649 } 650 651 return hs20_send_wnm_notification(hapd, addr, 1, url); 652} 653 654 655static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 656 const char *cmd) 657{ 658 u8 addr[ETH_ALEN]; 659 int code, reauth_delay, ret; 660 const char *pos; 661 size_t url_len; 662 struct wpabuf *req; 663 664 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 665 if (hwaddr_aton(cmd, addr)) 666 return -1; 667 668 pos = os_strchr(cmd, ' '); 669 if (pos == NULL) 670 return -1; 671 pos++; 672 code = atoi(pos); 673 674 pos = os_strchr(pos, ' '); 675 if (pos == NULL) 676 return -1; 677 pos++; 678 reauth_delay = atoi(pos); 679 680 url_len = 0; 681 pos = os_strchr(pos, ' '); 682 if (pos) { 683 pos++; 684 url_len = os_strlen(pos); 685 } 686 687 req = wpabuf_alloc(4 + url_len); 688 if (req == NULL) 689 return -1; 690 wpabuf_put_u8(req, code); 691 wpabuf_put_le16(req, reauth_delay); 692 wpabuf_put_u8(req, url_len); 693 if (pos) 694 wpabuf_put_data(req, pos, url_len); 695 696 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 697 " to indicate imminent deauthentication (code=%d " 698 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 699 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 700 wpabuf_free(req); 701 return ret; 702} 703 704#endif /* CONFIG_HS20 */ 705 706 707#ifdef CONFIG_INTERWORKING 708 709static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 710 const char *cmd) 711{ 712 u8 qos_map_set[16 + 2 * 21], count = 0; 713 const char *pos = cmd; 714 int val, ret; 715 716 for (;;) { 717 if (count == sizeof(qos_map_set)) { 718 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 719 return -1; 720 } 721 722 val = atoi(pos); 723 if (val < 0 || val > 255) { 724 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 725 return -1; 726 } 727 728 qos_map_set[count++] = val; 729 pos = os_strchr(pos, ','); 730 if (!pos) 731 break; 732 pos++; 733 } 734 735 if (count < 16 || count & 1) { 736 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 737 return -1; 738 } 739 740 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 741 if (ret) { 742 wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 743 return -1; 744 } 745 746 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 747 hapd->conf->qos_map_set_len = count; 748 749 return 0; 750} 751 752 753static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 754 const char *cmd) 755{ 756 u8 addr[ETH_ALEN]; 757 struct sta_info *sta; 758 struct wpabuf *buf; 759 u8 *qos_map_set = hapd->conf->qos_map_set; 760 u8 qos_map_set_len = hapd->conf->qos_map_set_len; 761 int ret; 762 763 if (!qos_map_set_len) { 764 wpa_printf(MSG_INFO, "QoS Map Set is not set"); 765 return -1; 766 } 767 768 if (hwaddr_aton(cmd, addr)) 769 return -1; 770 771 sta = ap_get_sta(hapd, addr); 772 if (sta == NULL) { 773 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 774 "for QoS Map Configuration message", 775 MAC2STR(addr)); 776 return -1; 777 } 778 779 if (!sta->qos_map_enabled) { 780 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 781 "support for QoS Map", MAC2STR(addr)); 782 return -1; 783 } 784 785 buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 786 if (buf == NULL) 787 return -1; 788 789 wpabuf_put_u8(buf, WLAN_ACTION_QOS); 790 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 791 792 /* QoS Map Set Element */ 793 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 794 wpabuf_put_u8(buf, qos_map_set_len); 795 wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 796 797 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 798 wpabuf_head(buf), wpabuf_len(buf)); 799 wpabuf_free(buf); 800 801 return ret; 802} 803 804#endif /* CONFIG_INTERWORKING */ 805 806 807#ifdef CONFIG_WNM 808 809static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 810 const char *cmd) 811{ 812 u8 addr[ETH_ALEN]; 813 int disassoc_timer; 814 struct sta_info *sta; 815 816 if (hwaddr_aton(cmd, addr)) 817 return -1; 818 if (cmd[17] != ' ') 819 return -1; 820 disassoc_timer = atoi(cmd + 17); 821 822 sta = ap_get_sta(hapd, addr); 823 if (sta == NULL) { 824 wpa_printf(MSG_DEBUG, "Station " MACSTR 825 " not found for disassociation imminent message", 826 MAC2STR(addr)); 827 return -1; 828 } 829 830 return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); 831} 832 833 834static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 835 const char *cmd) 836{ 837 u8 addr[ETH_ALEN]; 838 const char *url, *timerstr; 839 int disassoc_timer; 840 struct sta_info *sta; 841 842 if (hwaddr_aton(cmd, addr)) 843 return -1; 844 845 sta = ap_get_sta(hapd, addr); 846 if (sta == NULL) { 847 wpa_printf(MSG_DEBUG, "Station " MACSTR 848 " not found for ESS disassociation imminent message", 849 MAC2STR(addr)); 850 return -1; 851 } 852 853 timerstr = cmd + 17; 854 if (*timerstr != ' ') 855 return -1; 856 timerstr++; 857 disassoc_timer = atoi(timerstr); 858 if (disassoc_timer < 0 || disassoc_timer > 65535) 859 return -1; 860 861 url = os_strchr(timerstr, ' '); 862 if (url == NULL) 863 return -1; 864 url++; 865 866 return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); 867} 868 869 870static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, 871 const char *cmd) 872{ 873 u8 addr[ETH_ALEN]; 874 const char *pos, *end; 875 int disassoc_timer = 0; 876 struct sta_info *sta; 877 u8 req_mode = 0, valid_int = 0x01; 878 u8 bss_term_dur[12]; 879 char *url = NULL; 880 int ret; 881 u8 nei_rep[1000]; 882 u8 *nei_pos = nei_rep; 883 884 if (hwaddr_aton(cmd, addr)) { 885 wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 886 return -1; 887 } 888 889 sta = ap_get_sta(hapd, addr); 890 if (sta == NULL) { 891 wpa_printf(MSG_DEBUG, "Station " MACSTR 892 " not found for BSS TM Request message", 893 MAC2STR(addr)); 894 return -1; 895 } 896 897 pos = os_strstr(cmd, " disassoc_timer="); 898 if (pos) { 899 pos += 16; 900 disassoc_timer = atoi(pos); 901 if (disassoc_timer < 0 || disassoc_timer > 65535) { 902 wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); 903 return -1; 904 } 905 } 906 907 pos = os_strstr(cmd, " valid_int="); 908 if (pos) { 909 pos += 11; 910 valid_int = atoi(pos); 911 } 912 913 pos = os_strstr(cmd, " bss_term="); 914 if (pos) { 915 pos += 10; 916 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; 917 /* TODO: TSF configurable/learnable */ 918 bss_term_dur[0] = 4; /* Subelement ID */ 919 bss_term_dur[1] = 10; /* Length */ 920 os_memset(bss_term_dur, 2, 8); 921 end = os_strchr(pos, ','); 922 if (end == NULL) { 923 wpa_printf(MSG_DEBUG, "Invalid bss_term data"); 924 return -1; 925 } 926 end++; 927 WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); 928 } 929 930 931 /* 932 * BSS Transition Candidate List Entries - Neighbor Report elements 933 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>, 934 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>] 935 */ 936 pos = cmd; 937 while (pos) { 938 u8 *nei_start; 939 long int val; 940 char *endptr, *tmp; 941 942 pos = os_strstr(pos, " neighbor="); 943 if (!pos) 944 break; 945 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) { 946 wpa_printf(MSG_DEBUG, 947 "Not enough room for additional neighbor"); 948 return -1; 949 } 950 pos += 10; 951 952 nei_start = nei_pos; 953 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT; 954 nei_pos++; /* length to be filled in */ 955 956 if (hwaddr_aton(pos, nei_pos)) { 957 wpa_printf(MSG_DEBUG, "Invalid BSSID"); 958 return -1; 959 } 960 nei_pos += ETH_ALEN; 961 pos += 17; 962 if (*pos != ',') { 963 wpa_printf(MSG_DEBUG, "Missing BSSID Information"); 964 return -1; 965 } 966 pos++; 967 968 val = strtol(pos, &endptr, 0); 969 WPA_PUT_LE32(nei_pos, val); 970 nei_pos += 4; 971 if (*endptr != ',') { 972 wpa_printf(MSG_DEBUG, "Missing Operating Class"); 973 return -1; 974 } 975 pos = endptr + 1; 976 977 *nei_pos++ = atoi(pos); /* Operating Class */ 978 pos = os_strchr(pos, ','); 979 if (pos == NULL) { 980 wpa_printf(MSG_DEBUG, "Missing Channel Number"); 981 return -1; 982 } 983 pos++; 984 985 *nei_pos++ = atoi(pos); /* Channel Number */ 986 pos = os_strchr(pos, ','); 987 if (pos == NULL) { 988 wpa_printf(MSG_DEBUG, "Missing PHY Type"); 989 return -1; 990 } 991 pos++; 992 993 *nei_pos++ = atoi(pos); /* PHY Type */ 994 end = os_strchr(pos, ' '); 995 tmp = os_strchr(pos, ','); 996 if (tmp && (!end || tmp < end)) { 997 /* Optional Subelements (hexdump) */ 998 size_t len; 999 1000 pos = tmp + 1; 1001 end = os_strchr(pos, ' '); 1002 if (end) 1003 len = end - pos; 1004 else 1005 len = os_strlen(pos); 1006 if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) { 1007 wpa_printf(MSG_DEBUG, 1008 "Not enough room for neighbor subelements"); 1009 return -1; 1010 } 1011 if (len & 0x01 || 1012 hexstr2bin(pos, nei_pos, len / 2) < 0) { 1013 wpa_printf(MSG_DEBUG, 1014 "Invalid neighbor subelement info"); 1015 return -1; 1016 } 1017 nei_pos += len / 2; 1018 pos = end; 1019 } 1020 1021 nei_start[1] = nei_pos - nei_start - 2; 1022 } 1023 1024 pos = os_strstr(cmd, " url="); 1025 if (pos) { 1026 size_t len; 1027 pos += 5; 1028 end = os_strchr(pos, ' '); 1029 if (end) 1030 len = end - pos; 1031 else 1032 len = os_strlen(pos); 1033 url = os_malloc(len + 1); 1034 if (url == NULL) 1035 return -1; 1036 os_memcpy(url, pos, len); 1037 url[len] = '\0'; 1038 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 1039 } 1040 1041 if (os_strstr(cmd, " pref=1")) 1042 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; 1043 if (os_strstr(cmd, " abridged=1")) 1044 req_mode |= WNM_BSS_TM_REQ_ABRIDGED; 1045 if (os_strstr(cmd, " disassoc_imminent=1")) 1046 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 1047 1048 ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, 1049 valid_int, bss_term_dur, url, 1050 nei_pos > nei_rep ? nei_rep : NULL, 1051 nei_pos - nei_rep); 1052 os_free(url); 1053 return ret; 1054} 1055 1056#endif /* CONFIG_WNM */ 1057 1058 1059static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 1060 char *buf, size_t buflen) 1061{ 1062 int ret; 1063 char *pos, *end; 1064 1065 pos = buf; 1066 end = buf + buflen; 1067 1068 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 1069 "ssid=%s\n", 1070 MAC2STR(hapd->own_addr), 1071 wpa_ssid_txt(hapd->conf->ssid.ssid, 1072 hapd->conf->ssid.ssid_len)); 1073 if (os_snprintf_error(end - pos, ret)) 1074 return pos - buf; 1075 pos += ret; 1076 1077#ifdef CONFIG_WPS 1078 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 1079 hapd->conf->wps_state == 0 ? "disabled" : 1080 (hapd->conf->wps_state == 1 ? "not configured" : 1081 "configured")); 1082 if (os_snprintf_error(end - pos, ret)) 1083 return pos - buf; 1084 pos += ret; 1085 1086 if (hapd->conf->wps_state && hapd->conf->wpa && 1087 hapd->conf->ssid.wpa_passphrase) { 1088 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 1089 hapd->conf->ssid.wpa_passphrase); 1090 if (os_snprintf_error(end - pos, ret)) 1091 return pos - buf; 1092 pos += ret; 1093 } 1094 1095 if (hapd->conf->wps_state && hapd->conf->wpa && 1096 hapd->conf->ssid.wpa_psk && 1097 hapd->conf->ssid.wpa_psk->group) { 1098 char hex[PMK_LEN * 2 + 1]; 1099 wpa_snprintf_hex(hex, sizeof(hex), 1100 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 1101 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 1102 if (os_snprintf_error(end - pos, ret)) 1103 return pos - buf; 1104 pos += ret; 1105 } 1106#endif /* CONFIG_WPS */ 1107 1108 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 1109 ret = os_snprintf(pos, end - pos, "key_mgmt="); 1110 if (os_snprintf_error(end - pos, ret)) 1111 return pos - buf; 1112 pos += ret; 1113 1114 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 1115 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 1116 if (os_snprintf_error(end - pos, ret)) 1117 return pos - buf; 1118 pos += ret; 1119 } 1120 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1121 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 1122 if (os_snprintf_error(end - pos, ret)) 1123 return pos - buf; 1124 pos += ret; 1125 } 1126#ifdef CONFIG_IEEE80211R 1127 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1128 ret = os_snprintf(pos, end - pos, "FT-PSK "); 1129 if (os_snprintf_error(end - pos, ret)) 1130 return pos - buf; 1131 pos += ret; 1132 } 1133 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1134 ret = os_snprintf(pos, end - pos, "FT-EAP "); 1135 if (os_snprintf_error(end - pos, ret)) 1136 return pos - buf; 1137 pos += ret; 1138 } 1139#ifdef CONFIG_SAE 1140 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 1141 ret = os_snprintf(pos, end - pos, "FT-SAE "); 1142 if (os_snprintf_error(end - pos, ret)) 1143 return pos - buf; 1144 pos += ret; 1145 } 1146#endif /* CONFIG_SAE */ 1147#endif /* CONFIG_IEEE80211R */ 1148#ifdef CONFIG_IEEE80211W 1149 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1150 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 1151 if (os_snprintf_error(end - pos, ret)) 1152 return pos - buf; 1153 pos += ret; 1154 } 1155 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1156 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 1157 if (os_snprintf_error(end - pos, ret)) 1158 return pos - buf; 1159 pos += ret; 1160 } 1161#endif /* CONFIG_IEEE80211W */ 1162#ifdef CONFIG_SAE 1163 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 1164 ret = os_snprintf(pos, end - pos, "SAE "); 1165 if (os_snprintf_error(end - pos, ret)) 1166 return pos - buf; 1167 pos += ret; 1168 } 1169#endif /* CONFIG_SAE */ 1170 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 1171 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); 1172 if (os_snprintf_error(end - pos, ret)) 1173 return pos - buf; 1174 pos += ret; 1175 } 1176 if (hapd->conf->wpa_key_mgmt & 1177 WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 1178 ret = os_snprintf(pos, end - pos, 1179 "WPA-EAP-SUITE-B-192 "); 1180 if (os_snprintf_error(end - pos, ret)) 1181 return pos - buf; 1182 pos += ret; 1183 } 1184 1185 ret = os_snprintf(pos, end - pos, "\n"); 1186 if (os_snprintf_error(end - pos, ret)) 1187 return pos - buf; 1188 pos += ret; 1189 } 1190 1191 if (hapd->conf->wpa) { 1192 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 1193 wpa_cipher_txt(hapd->conf->wpa_group)); 1194 if (os_snprintf_error(end - pos, ret)) 1195 return pos - buf; 1196 pos += ret; 1197 } 1198 1199 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 1200 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 1201 if (os_snprintf_error(end - pos, ret)) 1202 return pos - buf; 1203 pos += ret; 1204 1205 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 1206 " "); 1207 if (ret < 0) 1208 return pos - buf; 1209 pos += ret; 1210 1211 ret = os_snprintf(pos, end - pos, "\n"); 1212 if (os_snprintf_error(end - pos, ret)) 1213 return pos - buf; 1214 pos += ret; 1215 } 1216 1217 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1218 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1219 if (os_snprintf_error(end - pos, ret)) 1220 return pos - buf; 1221 pos += ret; 1222 1223 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1224 " "); 1225 if (ret < 0) 1226 return pos - buf; 1227 pos += ret; 1228 1229 ret = os_snprintf(pos, end - pos, "\n"); 1230 if (os_snprintf_error(end - pos, ret)) 1231 return pos - buf; 1232 pos += ret; 1233 } 1234 1235 return pos - buf; 1236} 1237 1238 1239static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1240{ 1241 char *value; 1242 int ret = 0; 1243 1244 value = os_strchr(cmd, ' '); 1245 if (value == NULL) 1246 return -1; 1247 *value++ = '\0'; 1248 1249 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1250 if (0) { 1251#ifdef CONFIG_WPS_TESTING 1252 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1253 long int val; 1254 val = strtol(value, NULL, 0); 1255 if (val < 0 || val > 0xff) { 1256 ret = -1; 1257 wpa_printf(MSG_DEBUG, "WPS: Invalid " 1258 "wps_version_number %ld", val); 1259 } else { 1260 wps_version_number = val; 1261 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1262 "version %u.%u", 1263 (wps_version_number & 0xf0) >> 4, 1264 wps_version_number & 0x0f); 1265 hostapd_wps_update_ie(hapd); 1266 } 1267 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 1268 wps_testing_dummy_cred = atoi(value); 1269 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 1270 wps_testing_dummy_cred); 1271 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1272 wps_corrupt_pkhash = atoi(value); 1273 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1274 wps_corrupt_pkhash); 1275#endif /* CONFIG_WPS_TESTING */ 1276#ifdef CONFIG_INTERWORKING 1277 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) { 1278 int val = atoi(value); 1279 if (val <= 0) 1280 ret = -1; 1281 else 1282 hapd->gas_frag_limit = val; 1283#endif /* CONFIG_INTERWORKING */ 1284#ifdef CONFIG_TESTING_OPTIONS 1285 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1286 hapd->ext_mgmt_frame_handling = atoi(value); 1287 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 1288 hapd->ext_eapol_frame_io = atoi(value); 1289#endif /* CONFIG_TESTING_OPTIONS */ 1290 } else { 1291 struct sta_info *sta; 1292 int vlan_id; 1293 1294 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1295 if (ret) 1296 return ret; 1297 1298 if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1299 for (sta = hapd->sta_list; sta; sta = sta->next) { 1300 if (hostapd_maclist_found( 1301 hapd->conf->deny_mac, 1302 hapd->conf->num_deny_mac, sta->addr, 1303 &vlan_id) && 1304 (!vlan_id || vlan_id == sta->vlan_id)) 1305 ap_sta_disconnect( 1306 hapd, sta, sta->addr, 1307 WLAN_REASON_UNSPECIFIED); 1308 } 1309 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED && 1310 os_strcasecmp(cmd, "accept_mac_file") == 0) { 1311 for (sta = hapd->sta_list; sta; sta = sta->next) { 1312 if (!hostapd_maclist_found( 1313 hapd->conf->accept_mac, 1314 hapd->conf->num_accept_mac, 1315 sta->addr, &vlan_id) || 1316 (vlan_id && vlan_id != sta->vlan_id)) 1317 ap_sta_disconnect( 1318 hapd, sta, sta->addr, 1319 WLAN_REASON_UNSPECIFIED); 1320 } 1321 } 1322 } 1323 1324 return ret; 1325} 1326 1327 1328static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1329 char *buf, size_t buflen) 1330{ 1331 int res; 1332 1333 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1334 1335 if (os_strcmp(cmd, "version") == 0) { 1336 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1337 if (os_snprintf_error(buflen, res)) 1338 return -1; 1339 return res; 1340 } else if (os_strcmp(cmd, "tls_library") == 0) { 1341 res = tls_get_library_version(buf, buflen); 1342 if (os_snprintf_error(buflen, res)) 1343 return -1; 1344 return res; 1345 } 1346 1347 return -1; 1348} 1349 1350 1351static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1352{ 1353 if (hostapd_enable_iface(iface) < 0) { 1354 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1355 return -1; 1356 } 1357 return 0; 1358} 1359 1360 1361static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1362{ 1363 if (hostapd_reload_iface(iface) < 0) { 1364 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1365 return -1; 1366 } 1367 return 0; 1368} 1369 1370 1371static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1372{ 1373 if (hostapd_disable_iface(iface) < 0) { 1374 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1375 return -1; 1376 } 1377 return 0; 1378} 1379 1380 1381#ifdef CONFIG_TESTING_OPTIONS 1382 1383static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1384{ 1385 union wpa_event_data data; 1386 char *pos, *param; 1387 enum wpa_event_type event; 1388 1389 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1390 1391 os_memset(&data, 0, sizeof(data)); 1392 1393 param = os_strchr(cmd, ' '); 1394 if (param == NULL) 1395 return -1; 1396 *param++ = '\0'; 1397 1398 if (os_strcmp(cmd, "DETECTED") == 0) 1399 event = EVENT_DFS_RADAR_DETECTED; 1400 else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1401 event = EVENT_DFS_CAC_FINISHED; 1402 else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1403 event = EVENT_DFS_CAC_ABORTED; 1404 else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1405 event = EVENT_DFS_NOP_FINISHED; 1406 else { 1407 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1408 cmd); 1409 return -1; 1410 } 1411 1412 pos = os_strstr(param, "freq="); 1413 if (pos) 1414 data.dfs_event.freq = atoi(pos + 5); 1415 1416 pos = os_strstr(param, "ht_enabled=1"); 1417 if (pos) 1418 data.dfs_event.ht_enabled = 1; 1419 1420 pos = os_strstr(param, "chan_offset="); 1421 if (pos) 1422 data.dfs_event.chan_offset = atoi(pos + 12); 1423 1424 pos = os_strstr(param, "chan_width="); 1425 if (pos) 1426 data.dfs_event.chan_width = atoi(pos + 11); 1427 1428 pos = os_strstr(param, "cf1="); 1429 if (pos) 1430 data.dfs_event.cf1 = atoi(pos + 4); 1431 1432 pos = os_strstr(param, "cf2="); 1433 if (pos) 1434 data.dfs_event.cf2 = atoi(pos + 4); 1435 1436 wpa_supplicant_event(hapd, event, &data); 1437 1438 return 0; 1439} 1440 1441 1442static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1443{ 1444 size_t len; 1445 u8 *buf; 1446 int res; 1447 1448 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1449 1450 len = os_strlen(cmd); 1451 if (len & 1) 1452 return -1; 1453 len /= 2; 1454 1455 buf = os_malloc(len); 1456 if (buf == NULL) 1457 return -1; 1458 1459 if (hexstr2bin(cmd, buf, len) < 0) { 1460 os_free(buf); 1461 return -1; 1462 } 1463 1464 res = hostapd_drv_send_mlme(hapd, buf, len, 0); 1465 os_free(buf); 1466 return res; 1467} 1468 1469 1470static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd) 1471{ 1472 char *pos; 1473 u8 src[ETH_ALEN], *buf; 1474 int used; 1475 size_t len; 1476 1477 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 1478 1479 pos = cmd; 1480 used = hwaddr_aton2(pos, src); 1481 if (used < 0) 1482 return -1; 1483 pos += used; 1484 while (*pos == ' ') 1485 pos++; 1486 1487 len = os_strlen(pos); 1488 if (len & 1) 1489 return -1; 1490 len /= 2; 1491 1492 buf = os_malloc(len); 1493 if (buf == NULL) 1494 return -1; 1495 1496 if (hexstr2bin(pos, buf, len) < 0) { 1497 os_free(buf); 1498 return -1; 1499 } 1500 1501 ieee802_1x_receive(hapd, src, buf, len); 1502 os_free(buf); 1503 1504 return 0; 1505} 1506 1507 1508static u16 ipv4_hdr_checksum(const void *buf, size_t len) 1509{ 1510 size_t i; 1511 u32 sum = 0; 1512 const u16 *pos = buf; 1513 1514 for (i = 0; i < len / 2; i++) 1515 sum += *pos++; 1516 1517 while (sum >> 16) 1518 sum = (sum & 0xffff) + (sum >> 16); 1519 1520 return sum ^ 0xffff; 1521} 1522 1523 1524#define HWSIM_PACKETLEN 1500 1525#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 1526 1527void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 1528 size_t len) 1529{ 1530 struct hostapd_data *hapd = ctx; 1531 const struct ether_header *eth; 1532 const struct iphdr *ip; 1533 const u8 *pos; 1534 unsigned int i; 1535 1536 if (len != HWSIM_PACKETLEN) 1537 return; 1538 1539 eth = (const struct ether_header *) buf; 1540 ip = (const struct iphdr *) (eth + 1); 1541 pos = (const u8 *) (ip + 1); 1542 1543 if (ip->ihl != 5 || ip->version != 4 || 1544 ntohs(ip->tot_len) != HWSIM_IP_LEN) 1545 return; 1546 1547 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) { 1548 if (*pos != (u8) i) 1549 return; 1550 pos++; 1551 } 1552 1553 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR, 1554 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost)); 1555} 1556 1557 1558static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, 1559 char *cmd) 1560{ 1561 int enabled = atoi(cmd); 1562 char *pos; 1563 const char *ifname; 1564 1565 if (!enabled) { 1566 if (hapd->l2_test) { 1567 l2_packet_deinit(hapd->l2_test); 1568 hapd->l2_test = NULL; 1569 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1570 "test data: Disabled"); 1571 } 1572 return 0; 1573 } 1574 1575 if (hapd->l2_test) 1576 return 0; 1577 1578 pos = os_strstr(cmd, " ifname="); 1579 if (pos) 1580 ifname = pos + 8; 1581 else 1582 ifname = hapd->conf->iface; 1583 1584 hapd->l2_test = l2_packet_init(ifname, hapd->own_addr, 1585 ETHERTYPE_IP, hostapd_data_test_rx, 1586 hapd, 1); 1587 if (hapd->l2_test == NULL) 1588 return -1; 1589 1590 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled"); 1591 1592 return 0; 1593} 1594 1595 1596static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) 1597{ 1598 u8 dst[ETH_ALEN], src[ETH_ALEN]; 1599 char *pos; 1600 int used; 1601 long int val; 1602 u8 tos; 1603 u8 buf[HWSIM_PACKETLEN]; 1604 struct ether_header *eth; 1605 struct iphdr *ip; 1606 u8 *dpos; 1607 unsigned int i; 1608 1609 if (hapd->l2_test == NULL) 1610 return -1; 1611 1612 /* format: <dst> <src> <tos> */ 1613 1614 pos = cmd; 1615 used = hwaddr_aton2(pos, dst); 1616 if (used < 0) 1617 return -1; 1618 pos += used; 1619 while (*pos == ' ') 1620 pos++; 1621 used = hwaddr_aton2(pos, src); 1622 if (used < 0) 1623 return -1; 1624 pos += used; 1625 1626 val = strtol(pos, NULL, 0); 1627 if (val < 0 || val > 0xff) 1628 return -1; 1629 tos = val; 1630 1631 eth = (struct ether_header *) buf; 1632 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 1633 os_memcpy(eth->ether_shost, src, ETH_ALEN); 1634 eth->ether_type = htons(ETHERTYPE_IP); 1635 ip = (struct iphdr *) (eth + 1); 1636 os_memset(ip, 0, sizeof(*ip)); 1637 ip->ihl = 5; 1638 ip->version = 4; 1639 ip->ttl = 64; 1640 ip->tos = tos; 1641 ip->tot_len = htons(HWSIM_IP_LEN); 1642 ip->protocol = 1; 1643 ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1); 1644 ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2); 1645 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 1646 dpos = (u8 *) (ip + 1); 1647 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) 1648 *dpos++ = i; 1649 1650 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, buf, 1651 HWSIM_PACKETLEN) < 0) 1652 return -1; 1653 1654 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR 1655 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 1656 1657 return 0; 1658} 1659 1660 1661static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd, 1662 char *cmd) 1663{ 1664 u8 *buf; 1665 struct ether_header *eth; 1666 struct l2_packet_data *l2 = NULL; 1667 size_t len; 1668 u16 ethertype; 1669 int res = -1; 1670 const char *ifname = hapd->conf->iface; 1671 1672 if (os_strncmp(cmd, "ifname=", 7) == 0) { 1673 cmd += 7; 1674 ifname = cmd; 1675 cmd = os_strchr(cmd, ' '); 1676 if (cmd == NULL) 1677 return -1; 1678 *cmd++ = '\0'; 1679 } 1680 1681 len = os_strlen(cmd); 1682 if (len & 1 || len < ETH_HLEN * 2) 1683 return -1; 1684 len /= 2; 1685 1686 buf = os_malloc(len); 1687 if (buf == NULL) 1688 return -1; 1689 1690 if (hexstr2bin(cmd, buf, len) < 0) 1691 goto done; 1692 1693 eth = (struct ether_header *) buf; 1694 ethertype = ntohs(eth->ether_type); 1695 1696 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype, 1697 hostapd_data_test_rx, hapd, 1); 1698 if (l2 == NULL) 1699 goto done; 1700 1701 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 1702 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res); 1703done: 1704 if (l2) 1705 l2_packet_deinit(l2); 1706 os_free(buf); 1707 1708 return res < 0 ? -1 : 0; 1709} 1710 1711 1712static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd) 1713{ 1714#ifdef WPA_TRACE_BFD 1715 extern char wpa_trace_fail_func[256]; 1716 extern unsigned int wpa_trace_fail_after; 1717 char *pos; 1718 1719 wpa_trace_fail_after = atoi(cmd); 1720 pos = os_strchr(cmd, ':'); 1721 if (pos) { 1722 pos++; 1723 os_strlcpy(wpa_trace_fail_func, pos, 1724 sizeof(wpa_trace_fail_func)); 1725 } else { 1726 wpa_trace_fail_after = 0; 1727 } 1728 1729 return 0; 1730#else /* WPA_TRACE_BFD */ 1731 return -1; 1732#endif /* WPA_TRACE_BFD */ 1733} 1734 1735 1736static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd, 1737 char *buf, size_t buflen) 1738{ 1739#ifdef WPA_TRACE_BFD 1740 extern char wpa_trace_fail_func[256]; 1741 extern unsigned int wpa_trace_fail_after; 1742 1743 return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after, 1744 wpa_trace_fail_func); 1745#else /* WPA_TRACE_BFD */ 1746 return -1; 1747#endif /* WPA_TRACE_BFD */ 1748} 1749 1750#endif /* CONFIG_TESTING_OPTIONS */ 1751 1752 1753static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 1754 char *pos) 1755{ 1756#ifdef NEED_AP_MLME 1757 struct csa_settings settings; 1758 int ret; 1759 unsigned int i; 1760 1761 ret = hostapd_parse_csa_settings(pos, &settings); 1762 if (ret) 1763 return ret; 1764 1765 for (i = 0; i < iface->num_bss; i++) { 1766 ret = hostapd_switch_channel(iface->bss[i], &settings); 1767 if (ret) { 1768 /* FIX: What do we do if CSA fails in the middle of 1769 * submitting multi-BSS CSA requests? */ 1770 return ret; 1771 } 1772 } 1773 1774 return 0; 1775#else /* NEED_AP_MLME */ 1776 return -1; 1777#endif /* NEED_AP_MLME */ 1778} 1779 1780 1781static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 1782 int reply_size, const char *param) 1783{ 1784#ifdef RADIUS_SERVER 1785 if (os_strcmp(param, "radius_server") == 0) { 1786 return radius_server_get_mib(hapd->radius_srv, reply, 1787 reply_size); 1788 } 1789#endif /* RADIUS_SERVER */ 1790 return -1; 1791} 1792 1793 1794static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 1795 char *buf, size_t buflen) 1796{ 1797 int ret; 1798 char *pos; 1799 u8 *data = NULL; 1800 unsigned int vendor_id, subcmd; 1801 struct wpabuf *reply; 1802 size_t data_len = 0; 1803 1804 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 1805 vendor_id = strtoul(cmd, &pos, 16); 1806 if (!isblank(*pos)) 1807 return -EINVAL; 1808 1809 subcmd = strtoul(pos, &pos, 10); 1810 1811 if (*pos != '\0') { 1812 if (!isblank(*pos++)) 1813 return -EINVAL; 1814 data_len = os_strlen(pos); 1815 } 1816 1817 if (data_len) { 1818 data_len /= 2; 1819 data = os_malloc(data_len); 1820 if (!data) 1821 return -ENOBUFS; 1822 1823 if (hexstr2bin(pos, data, data_len)) { 1824 wpa_printf(MSG_DEBUG, 1825 "Vendor command: wrong parameter format"); 1826 os_free(data); 1827 return -EINVAL; 1828 } 1829 } 1830 1831 reply = wpabuf_alloc((buflen - 1) / 2); 1832 if (!reply) { 1833 os_free(data); 1834 return -ENOBUFS; 1835 } 1836 1837 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 1838 reply); 1839 1840 if (ret == 0) 1841 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 1842 wpabuf_len(reply)); 1843 1844 wpabuf_free(reply); 1845 os_free(data); 1846 1847 return ret; 1848} 1849 1850 1851static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 1852 void *sock_ctx) 1853{ 1854 struct hostapd_data *hapd = eloop_ctx; 1855 char buf[4096]; 1856 int res; 1857 struct sockaddr_un from; 1858 socklen_t fromlen = sizeof(from); 1859 char *reply; 1860 const int reply_size = 4096; 1861 int reply_len; 1862 int level = MSG_DEBUG; 1863 1864 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1865 (struct sockaddr *) &from, &fromlen); 1866 if (res < 0) { 1867 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 1868 strerror(errno)); 1869 return; 1870 } 1871 buf[res] = '\0'; 1872 if (os_strcmp(buf, "PING") == 0) 1873 level = MSG_EXCESSIVE; 1874 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 1875 1876 reply = os_malloc(reply_size); 1877 if (reply == NULL) { 1878 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 1879 fromlen) < 0) { 1880 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 1881 strerror(errno)); 1882 } 1883 return; 1884 } 1885 1886 os_memcpy(reply, "OK\n", 3); 1887 reply_len = 3; 1888 1889 if (os_strcmp(buf, "PING") == 0) { 1890 os_memcpy(reply, "PONG\n", 5); 1891 reply_len = 5; 1892 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 1893 if (wpa_debug_reopen_file() < 0) 1894 reply_len = -1; 1895 } else if (os_strcmp(buf, "STATUS") == 0) { 1896 reply_len = hostapd_ctrl_iface_status(hapd, reply, 1897 reply_size); 1898 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 1899 reply_len = hostapd_drv_status(hapd, reply, reply_size); 1900 } else if (os_strcmp(buf, "MIB") == 0) { 1901 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 1902 if (reply_len >= 0) { 1903 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 1904 reply_size - reply_len); 1905 if (res < 0) 1906 reply_len = -1; 1907 else 1908 reply_len += res; 1909 } 1910 if (reply_len >= 0) { 1911 res = ieee802_1x_get_mib(hapd, reply + reply_len, 1912 reply_size - reply_len); 1913 if (res < 0) 1914 reply_len = -1; 1915 else 1916 reply_len += res; 1917 } 1918#ifndef CONFIG_NO_RADIUS 1919 if (reply_len >= 0) { 1920 res = radius_client_get_mib(hapd->radius, 1921 reply + reply_len, 1922 reply_size - reply_len); 1923 if (res < 0) 1924 reply_len = -1; 1925 else 1926 reply_len += res; 1927 } 1928#endif /* CONFIG_NO_RADIUS */ 1929 } else if (os_strncmp(buf, "MIB ", 4) == 0) { 1930 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 1931 buf + 4); 1932 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 1933 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 1934 reply_size); 1935 } else if (os_strncmp(buf, "STA ", 4) == 0) { 1936 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 1937 reply_size); 1938 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 1939 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 1940 reply_size); 1941 } else if (os_strcmp(buf, "ATTACH") == 0) { 1942 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 1943 reply_len = -1; 1944 } else if (os_strcmp(buf, "DETACH") == 0) { 1945 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 1946 reply_len = -1; 1947 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 1948 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 1949 buf + 6)) 1950 reply_len = -1; 1951 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 1952 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 1953 reply_len = -1; 1954 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 1955 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 1956 reply_len = -1; 1957 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 1958 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 1959 reply_len = -1; 1960 } else if (os_strcmp(buf, "STOP_AP") == 0) { 1961 if (hostapd_ctrl_iface_stop_ap(hapd)) 1962 reply_len = -1; 1963#ifdef CONFIG_IEEE80211W 1964#ifdef NEED_AP_MLME 1965 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 1966 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 1967 reply_len = -1; 1968#endif /* NEED_AP_MLME */ 1969#endif /* CONFIG_IEEE80211W */ 1970#ifdef CONFIG_WPS 1971 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1972 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 1973 reply_len = -1; 1974 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 1975 reply_len = hostapd_ctrl_iface_wps_check_pin( 1976 hapd, buf + 14, reply, reply_size); 1977 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1978 if (hostapd_wps_button_pushed(hapd, NULL)) 1979 reply_len = -1; 1980 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 1981 if (hostapd_wps_cancel(hapd)) 1982 reply_len = -1; 1983 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 1984 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 1985 reply, reply_size); 1986 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 1987 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 1988 reply_len = -1; 1989 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 1990 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 1991 reply_size); 1992#ifdef CONFIG_WPS_NFC 1993 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 1994 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 1995 reply_len = -1; 1996 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 1997 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 1998 hapd, buf + 21, reply, reply_size); 1999 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 2000 reply_len = hostapd_ctrl_iface_wps_nfc_token( 2001 hapd, buf + 14, reply, reply_size); 2002 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 2003 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 2004 hapd, buf + 21, reply, reply_size); 2005 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 2006 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 2007 reply_len = -1; 2008#endif /* CONFIG_WPS_NFC */ 2009#endif /* CONFIG_WPS */ 2010#ifdef CONFIG_INTERWORKING 2011 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 2012 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 2013 reply_len = -1; 2014 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 2015 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 2016 reply_len = -1; 2017#endif /* CONFIG_INTERWORKING */ 2018#ifdef CONFIG_HS20 2019 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 2020 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 2021 reply_len = -1; 2022 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 2023 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 2024 reply_len = -1; 2025#endif /* CONFIG_HS20 */ 2026#ifdef CONFIG_WNM 2027 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 2028 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 2029 reply_len = -1; 2030 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 2031 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 2032 reply_len = -1; 2033 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 2034 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) 2035 reply_len = -1; 2036#endif /* CONFIG_WNM */ 2037 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 2038 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 2039 reply_size); 2040 } else if (os_strncmp(buf, "SET ", 4) == 0) { 2041 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 2042 reply_len = -1; 2043 } else if (os_strncmp(buf, "GET ", 4) == 0) { 2044 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 2045 reply_size); 2046 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 2047 if (hostapd_ctrl_iface_enable(hapd->iface)) 2048 reply_len = -1; 2049 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 2050 if (hostapd_ctrl_iface_reload(hapd->iface)) 2051 reply_len = -1; 2052 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 2053 if (hostapd_ctrl_iface_disable(hapd->iface)) 2054 reply_len = -1; 2055 } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) { 2056 if (ieee802_11_set_beacon(hapd)) 2057 reply_len = -1; 2058#ifdef CONFIG_TESTING_OPTIONS 2059 } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 2060 if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 2061 reply_len = -1; 2062 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 2063 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 2064 reply_len = -1; 2065 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 2066 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0) 2067 reply_len = -1; 2068 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 2069 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0) 2070 reply_len = -1; 2071 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 2072 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0) 2073 reply_len = -1; 2074 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 2075 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0) 2076 reply_len = -1; 2077 } else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) { 2078 if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0) 2079 reply_len = -1; 2080 } else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) { 2081 reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply, 2082 reply_size); 2083#endif /* CONFIG_TESTING_OPTIONS */ 2084 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 2085 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 2086 reply_len = -1; 2087 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 2088 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 2089 reply_size); 2090 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 2091 ieee802_1x_erp_flush(hapd); 2092#ifdef RADIUS_SERVER 2093 radius_server_erp_flush(hapd->radius_srv); 2094#endif /* RADIUS_SERVER */ 2095 } else { 2096 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 2097 reply_len = 16; 2098 } 2099 2100 if (reply_len < 0) { 2101 os_memcpy(reply, "FAIL\n", 5); 2102 reply_len = 5; 2103 } 2104 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 2105 fromlen) < 0) { 2106 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2107 strerror(errno)); 2108 } 2109 os_free(reply); 2110} 2111 2112 2113static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 2114{ 2115 char *buf; 2116 size_t len; 2117 2118 if (hapd->conf->ctrl_interface == NULL) 2119 return NULL; 2120 2121 len = os_strlen(hapd->conf->ctrl_interface) + 2122 os_strlen(hapd->conf->iface) + 2; 2123 buf = os_malloc(len); 2124 if (buf == NULL) 2125 return NULL; 2126 2127 os_snprintf(buf, len, "%s/%s", 2128 hapd->conf->ctrl_interface, hapd->conf->iface); 2129 buf[len - 1] = '\0'; 2130 return buf; 2131} 2132 2133 2134static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 2135 enum wpa_msg_type type, 2136 const char *txt, size_t len) 2137{ 2138 struct hostapd_data *hapd = ctx; 2139 if (hapd == NULL) 2140 return; 2141 hostapd_ctrl_iface_send(hapd, level, type, txt, len); 2142} 2143 2144 2145int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 2146{ 2147 struct sockaddr_un addr; 2148 int s = -1; 2149 char *fname = NULL; 2150 2151 if (hapd->ctrl_sock > -1) { 2152 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 2153 return 0; 2154 } 2155 2156 if (hapd->conf->ctrl_interface == NULL) 2157 return 0; 2158 2159 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2160 if (errno == EEXIST) { 2161 wpa_printf(MSG_DEBUG, "Using existing control " 2162 "interface directory."); 2163 } else { 2164 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 2165 strerror(errno)); 2166 goto fail; 2167 } 2168 } 2169 2170 if (hapd->conf->ctrl_interface_gid_set && 2171 chown(hapd->conf->ctrl_interface, -1, 2172 hapd->conf->ctrl_interface_gid) < 0) { 2173 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2174 strerror(errno)); 2175 return -1; 2176 } 2177 2178 if (!hapd->conf->ctrl_interface_gid_set && 2179 hapd->iface->interfaces->ctrl_iface_group && 2180 chown(hapd->conf->ctrl_interface, -1, 2181 hapd->iface->interfaces->ctrl_iface_group) < 0) { 2182 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2183 strerror(errno)); 2184 return -1; 2185 } 2186 2187#ifdef ANDROID 2188 /* 2189 * Android is using umask 0077 which would leave the control interface 2190 * directory without group access. This breaks things since Wi-Fi 2191 * framework assumes that this directory can be accessed by other 2192 * applications in the wifi group. Fix this by adding group access even 2193 * if umask value would prevent this. 2194 */ 2195 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2196 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 2197 strerror(errno)); 2198 /* Try to continue anyway */ 2199 } 2200#endif /* ANDROID */ 2201 2202 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 2203 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 2204 goto fail; 2205 2206 s = socket(PF_UNIX, SOCK_DGRAM, 0); 2207 if (s < 0) { 2208 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 2209 goto fail; 2210 } 2211 2212 os_memset(&addr, 0, sizeof(addr)); 2213#ifdef __FreeBSD__ 2214 addr.sun_len = sizeof(addr); 2215#endif /* __FreeBSD__ */ 2216 addr.sun_family = AF_UNIX; 2217 fname = hostapd_ctrl_iface_path(hapd); 2218 if (fname == NULL) 2219 goto fail; 2220 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 2221 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2222 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 2223 strerror(errno)); 2224 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2225 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 2226 " allow connections - assuming it was left" 2227 "over from forced program termination"); 2228 if (unlink(fname) < 0) { 2229 wpa_printf(MSG_ERROR, 2230 "Could not unlink existing ctrl_iface socket '%s': %s", 2231 fname, strerror(errno)); 2232 goto fail; 2233 } 2234 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 2235 0) { 2236 wpa_printf(MSG_ERROR, 2237 "hostapd-ctrl-iface: bind(PF_UNIX): %s", 2238 strerror(errno)); 2239 goto fail; 2240 } 2241 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 2242 "ctrl_iface socket '%s'", fname); 2243 } else { 2244 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 2245 "be in use - cannot override it"); 2246 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 2247 "not used anymore", fname); 2248 os_free(fname); 2249 fname = NULL; 2250 goto fail; 2251 } 2252 } 2253 2254 if (hapd->conf->ctrl_interface_gid_set && 2255 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 2256 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 2257 strerror(errno)); 2258 goto fail; 2259 } 2260 2261 if (!hapd->conf->ctrl_interface_gid_set && 2262 hapd->iface->interfaces->ctrl_iface_group && 2263 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 2264 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 2265 strerror(errno)); 2266 goto fail; 2267 } 2268 2269 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 2270 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 2271 strerror(errno)); 2272 goto fail; 2273 } 2274 os_free(fname); 2275 2276 hapd->ctrl_sock = s; 2277 if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 2278 NULL) < 0) { 2279 hostapd_ctrl_iface_deinit(hapd); 2280 return -1; 2281 } 2282 hapd->msg_ctx = hapd; 2283 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 2284 2285 return 0; 2286 2287fail: 2288 if (s >= 0) 2289 close(s); 2290 if (fname) { 2291 unlink(fname); 2292 os_free(fname); 2293 } 2294 return -1; 2295} 2296 2297 2298void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 2299{ 2300 struct wpa_ctrl_dst *dst, *prev; 2301 2302 if (hapd->ctrl_sock > -1) { 2303 char *fname; 2304 eloop_unregister_read_sock(hapd->ctrl_sock); 2305 close(hapd->ctrl_sock); 2306 hapd->ctrl_sock = -1; 2307 fname = hostapd_ctrl_iface_path(hapd); 2308 if (fname) 2309 unlink(fname); 2310 os_free(fname); 2311 2312 if (hapd->conf->ctrl_interface && 2313 rmdir(hapd->conf->ctrl_interface) < 0) { 2314 if (errno == ENOTEMPTY) { 2315 wpa_printf(MSG_DEBUG, "Control interface " 2316 "directory not empty - leaving it " 2317 "behind"); 2318 } else { 2319 wpa_printf(MSG_ERROR, 2320 "rmdir[ctrl_interface=%s]: %s", 2321 hapd->conf->ctrl_interface, 2322 strerror(errno)); 2323 } 2324 } 2325 } 2326 2327 dst = hapd->ctrl_dst; 2328 hapd->ctrl_dst = NULL; 2329 while (dst) { 2330 prev = dst; 2331 dst = dst->next; 2332 os_free(prev); 2333 } 2334 2335#ifdef CONFIG_TESTING_OPTIONS 2336 l2_packet_deinit(hapd->l2_test); 2337 hapd->l2_test = NULL; 2338#endif /* CONFIG_TESTING_OPTIONS */ 2339} 2340 2341 2342static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 2343 char *buf) 2344{ 2345 if (hostapd_add_iface(interfaces, buf) < 0) { 2346 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 2347 return -1; 2348 } 2349 return 0; 2350} 2351 2352 2353static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 2354 char *buf) 2355{ 2356 if (hostapd_remove_iface(interfaces, buf) < 0) { 2357 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 2358 return -1; 2359 } 2360 return 0; 2361} 2362 2363 2364static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces, 2365 struct sockaddr_un *from, 2366 socklen_t fromlen) 2367{ 2368 struct wpa_ctrl_dst *dst; 2369 2370 dst = os_zalloc(sizeof(*dst)); 2371 if (dst == NULL) 2372 return -1; 2373 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 2374 dst->addrlen = fromlen; 2375 dst->debug_level = MSG_INFO; 2376 dst->next = interfaces->global_ctrl_dst; 2377 interfaces->global_ctrl_dst = dst; 2378 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)", 2379 from->sun_path, 2380 fromlen - offsetof(struct sockaddr_un, sun_path)); 2381 return 0; 2382} 2383 2384 2385static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces, 2386 struct sockaddr_un *from, 2387 socklen_t fromlen) 2388{ 2389 struct wpa_ctrl_dst *dst, *prev = NULL; 2390 2391 dst = interfaces->global_ctrl_dst; 2392 while (dst) { 2393 if (fromlen == dst->addrlen && 2394 os_memcmp(from->sun_path, dst->addr.sun_path, 2395 fromlen - offsetof(struct sockaddr_un, sun_path)) 2396 == 0) { 2397 wpa_hexdump(MSG_DEBUG, 2398 "CTRL_IFACE monitor detached (global)", 2399 from->sun_path, 2400 fromlen - 2401 offsetof(struct sockaddr_un, sun_path)); 2402 if (prev == NULL) 2403 interfaces->global_ctrl_dst = dst->next; 2404 else 2405 prev->next = dst->next; 2406 os_free(dst); 2407 return 0; 2408 } 2409 prev = dst; 2410 dst = dst->next; 2411 } 2412 return -1; 2413} 2414 2415 2416static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 2417{ 2418#ifdef CONFIG_WPS_TESTING 2419 wps_version_number = 0x20; 2420 wps_testing_dummy_cred = 0; 2421 wps_corrupt_pkhash = 0; 2422#endif /* CONFIG_WPS_TESTING */ 2423} 2424 2425 2426static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 2427 void *sock_ctx) 2428{ 2429 void *interfaces = eloop_ctx; 2430 char buf[256]; 2431 int res; 2432 struct sockaddr_un from; 2433 socklen_t fromlen = sizeof(from); 2434 char *reply; 2435 int reply_len; 2436 const int reply_size = 4096; 2437 2438 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 2439 (struct sockaddr *) &from, &fromlen); 2440 if (res < 0) { 2441 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 2442 strerror(errno)); 2443 return; 2444 } 2445 buf[res] = '\0'; 2446 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 2447 2448 reply = os_malloc(reply_size); 2449 if (reply == NULL) { 2450 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 2451 fromlen) < 0) { 2452 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2453 strerror(errno)); 2454 } 2455 return; 2456 } 2457 2458 os_memcpy(reply, "OK\n", 3); 2459 reply_len = 3; 2460 2461 if (os_strcmp(buf, "PING") == 0) { 2462 os_memcpy(reply, "PONG\n", 5); 2463 reply_len = 5; 2464 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 2465 if (wpa_debug_reopen_file() < 0) 2466 reply_len = -1; 2467 } else if (os_strcmp(buf, "FLUSH") == 0) { 2468 hostapd_ctrl_iface_flush(interfaces); 2469 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 2470 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 2471 reply_len = -1; 2472 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 2473 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 2474 reply_len = -1; 2475 } else if (os_strcmp(buf, "ATTACH") == 0) { 2476 if (hostapd_global_ctrl_iface_attach(interfaces, &from, 2477 fromlen)) 2478 reply_len = -1; 2479 } else if (os_strcmp(buf, "DETACH") == 0) { 2480 if (hostapd_global_ctrl_iface_detach(interfaces, &from, 2481 fromlen)) 2482 reply_len = -1; 2483#ifdef CONFIG_MODULE_TESTS 2484 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 2485 int hapd_module_tests(void); 2486 if (hapd_module_tests() < 0) 2487 reply_len = -1; 2488#endif /* CONFIG_MODULE_TESTS */ 2489 } else { 2490 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 2491 "ignored"); 2492 reply_len = -1; 2493 } 2494 2495 if (reply_len < 0) { 2496 os_memcpy(reply, "FAIL\n", 5); 2497 reply_len = 5; 2498 } 2499 2500 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 2501 fromlen) < 0) { 2502 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2503 strerror(errno)); 2504 } 2505 os_free(reply); 2506} 2507 2508 2509static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 2510{ 2511 char *buf; 2512 size_t len; 2513 2514 if (interface->global_iface_path == NULL) 2515 return NULL; 2516 2517 len = os_strlen(interface->global_iface_path) + 2518 os_strlen(interface->global_iface_name) + 2; 2519 buf = os_malloc(len); 2520 if (buf == NULL) 2521 return NULL; 2522 2523 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 2524 interface->global_iface_name); 2525 buf[len - 1] = '\0'; 2526 return buf; 2527} 2528 2529 2530int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 2531{ 2532 struct sockaddr_un addr; 2533 int s = -1; 2534 char *fname = NULL; 2535 2536 if (interface->global_iface_path == NULL) { 2537 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 2538 return 0; 2539 } 2540 2541 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 2542 if (errno == EEXIST) { 2543 wpa_printf(MSG_DEBUG, "Using existing control " 2544 "interface directory."); 2545 } else { 2546 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 2547 strerror(errno)); 2548 goto fail; 2549 } 2550 } else if (interface->ctrl_iface_group && 2551 chown(interface->global_iface_path, -1, 2552 interface->ctrl_iface_group) < 0) { 2553 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2554 strerror(errno)); 2555 goto fail; 2556 } 2557 2558 if (os_strlen(interface->global_iface_path) + 1 + 2559 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 2560 goto fail; 2561 2562 s = socket(PF_UNIX, SOCK_DGRAM, 0); 2563 if (s < 0) { 2564 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 2565 goto fail; 2566 } 2567 2568 os_memset(&addr, 0, sizeof(addr)); 2569#ifdef __FreeBSD__ 2570 addr.sun_len = sizeof(addr); 2571#endif /* __FreeBSD__ */ 2572 addr.sun_family = AF_UNIX; 2573 fname = hostapd_global_ctrl_iface_path(interface); 2574 if (fname == NULL) 2575 goto fail; 2576 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 2577 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2578 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 2579 strerror(errno)); 2580 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2581 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 2582 " allow connections - assuming it was left" 2583 "over from forced program termination"); 2584 if (unlink(fname) < 0) { 2585 wpa_printf(MSG_ERROR, 2586 "Could not unlink existing ctrl_iface socket '%s': %s", 2587 fname, strerror(errno)); 2588 goto fail; 2589 } 2590 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 2591 0) { 2592 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s", 2593 strerror(errno)); 2594 goto fail; 2595 } 2596 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 2597 "ctrl_iface socket '%s'", fname); 2598 } else { 2599 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 2600 "be in use - cannot override it"); 2601 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 2602 "not used anymore", fname); 2603 os_free(fname); 2604 fname = NULL; 2605 goto fail; 2606 } 2607 } 2608 2609 if (interface->ctrl_iface_group && 2610 chown(fname, -1, interface->ctrl_iface_group) < 0) { 2611 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2612 strerror(errno)); 2613 goto fail; 2614 } 2615 2616 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 2617 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 2618 strerror(errno)); 2619 goto fail; 2620 } 2621 os_free(fname); 2622 2623 interface->global_ctrl_sock = s; 2624 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 2625 interface, NULL); 2626 2627 return 0; 2628 2629fail: 2630 if (s >= 0) 2631 close(s); 2632 if (fname) { 2633 unlink(fname); 2634 os_free(fname); 2635 } 2636 return -1; 2637} 2638 2639 2640void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 2641{ 2642 char *fname = NULL; 2643 struct wpa_ctrl_dst *dst, *prev; 2644 2645 if (interfaces->global_ctrl_sock > -1) { 2646 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 2647 close(interfaces->global_ctrl_sock); 2648 interfaces->global_ctrl_sock = -1; 2649 fname = hostapd_global_ctrl_iface_path(interfaces); 2650 if (fname) { 2651 unlink(fname); 2652 os_free(fname); 2653 } 2654 2655 if (interfaces->global_iface_path && 2656 rmdir(interfaces->global_iface_path) < 0) { 2657 if (errno == ENOTEMPTY) { 2658 wpa_printf(MSG_DEBUG, "Control interface " 2659 "directory not empty - leaving it " 2660 "behind"); 2661 } else { 2662 wpa_printf(MSG_ERROR, 2663 "rmdir[ctrl_interface=%s]: %s", 2664 interfaces->global_iface_path, 2665 strerror(errno)); 2666 } 2667 } 2668 } 2669 2670 os_free(interfaces->global_iface_path); 2671 interfaces->global_iface_path = NULL; 2672 2673 dst = interfaces->global_ctrl_dst; 2674 interfaces->global_ctrl_dst = NULL; 2675 while (dst) { 2676 prev = dst; 2677 dst = dst->next; 2678 os_free(prev); 2679 } 2680} 2681 2682 2683static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 2684 enum wpa_msg_type type, 2685 const char *buf, size_t len) 2686{ 2687 struct wpa_ctrl_dst *dst, *next; 2688 struct msghdr msg; 2689 int idx; 2690 struct iovec io[2]; 2691 char levelstr[10]; 2692 int s; 2693 2694 if (type != WPA_MSG_ONLY_GLOBAL) { 2695 s = hapd->ctrl_sock; 2696 dst = hapd->ctrl_dst; 2697 } else { 2698 s = hapd->iface->interfaces->global_ctrl_sock; 2699 dst = hapd->iface->interfaces->global_ctrl_dst; 2700 } 2701 2702 if (s < 0 || dst == NULL) 2703 return; 2704 2705 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 2706 io[0].iov_base = levelstr; 2707 io[0].iov_len = os_strlen(levelstr); 2708 io[1].iov_base = (char *) buf; 2709 io[1].iov_len = len; 2710 os_memset(&msg, 0, sizeof(msg)); 2711 msg.msg_iov = io; 2712 msg.msg_iovlen = 2; 2713 2714 idx = 0; 2715 while (dst) { 2716 next = dst->next; 2717 if (level >= dst->debug_level) { 2718 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 2719 (u8 *) dst->addr.sun_path, dst->addrlen - 2720 offsetof(struct sockaddr_un, sun_path)); 2721 msg.msg_name = &dst->addr; 2722 msg.msg_namelen = dst->addrlen; 2723 if (sendmsg(s, &msg, 0) < 0) { 2724 int _errno = errno; 2725 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 2726 "%d - %s", 2727 idx, errno, strerror(errno)); 2728 dst->errors++; 2729 if (dst->errors > 10 || _errno == ENOENT) { 2730 if (type != WPA_MSG_ONLY_GLOBAL) 2731 hostapd_ctrl_iface_detach( 2732 hapd, &dst->addr, 2733 dst->addrlen); 2734 else 2735 hostapd_global_ctrl_iface_detach( 2736 hapd->iface->interfaces, 2737 &dst->addr, 2738 dst->addrlen); 2739 } 2740 } else 2741 dst->errors = 0; 2742 } 2743 idx++; 2744 dst = next; 2745 } 2746} 2747 2748#endif /* CONFIG_NATIVE_WINDOWS */ 2749