1/* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2014, 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#include <sys/un.h> 14#include <sys/stat.h> 15#include <stddef.h> 16 17#include "utils/common.h" 18#include "utils/eloop.h" 19#include "common/version.h" 20#include "common/ieee802_11_defs.h" 21#include "drivers/driver.h" 22#include "radius/radius_client.h" 23#include "radius/radius_server.h" 24#include "ap/hostapd.h" 25#include "ap/ap_config.h" 26#include "ap/ieee802_1x.h" 27#include "ap/wpa_auth.h" 28#include "ap/ieee802_11.h" 29#include "ap/sta_info.h" 30#include "ap/wps_hostapd.h" 31#include "ap/ctrl_iface_ap.h" 32#include "ap/ap_drv_ops.h" 33#include "ap/hs20.h" 34#include "ap/wnm_ap.h" 35#include "ap/wpa_auth.h" 36#include "wps/wps_defs.h" 37#include "wps/wps.h" 38#include "config_file.h" 39#include "ctrl_iface.h" 40 41 42struct wpa_ctrl_dst { 43 struct wpa_ctrl_dst *next; 44 struct sockaddr_un addr; 45 socklen_t addrlen; 46 int debug_level; 47 int errors; 48}; 49 50 51static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 52 const char *buf, size_t len); 53 54 55static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 56 struct sockaddr_un *from, 57 socklen_t fromlen) 58{ 59 struct wpa_ctrl_dst *dst; 60 61 dst = os_zalloc(sizeof(*dst)); 62 if (dst == NULL) 63 return -1; 64 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 65 dst->addrlen = fromlen; 66 dst->debug_level = MSG_INFO; 67 dst->next = hapd->ctrl_dst; 68 hapd->ctrl_dst = dst; 69 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 70 (u8 *) from->sun_path, 71 fromlen - offsetof(struct sockaddr_un, sun_path)); 72 return 0; 73} 74 75 76static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 77 struct sockaddr_un *from, 78 socklen_t fromlen) 79{ 80 struct wpa_ctrl_dst *dst, *prev = NULL; 81 82 dst = hapd->ctrl_dst; 83 while (dst) { 84 if (fromlen == dst->addrlen && 85 os_memcmp(from->sun_path, dst->addr.sun_path, 86 fromlen - offsetof(struct sockaddr_un, sun_path)) 87 == 0) { 88 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 89 (u8 *) from->sun_path, 90 fromlen - 91 offsetof(struct sockaddr_un, sun_path)); 92 if (prev == NULL) 93 hapd->ctrl_dst = dst->next; 94 else 95 prev->next = dst->next; 96 os_free(dst); 97 return 0; 98 } 99 prev = dst; 100 dst = dst->next; 101 } 102 return -1; 103} 104 105 106static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 107 struct sockaddr_un *from, 108 socklen_t fromlen, 109 char *level) 110{ 111 struct wpa_ctrl_dst *dst; 112 113 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 114 115 dst = hapd->ctrl_dst; 116 while (dst) { 117 if (fromlen == dst->addrlen && 118 os_memcmp(from->sun_path, dst->addr.sun_path, 119 fromlen - offsetof(struct sockaddr_un, sun_path)) 120 == 0) { 121 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 122 "level", (u8 *) from->sun_path, fromlen - 123 offsetof(struct sockaddr_un, sun_path)); 124 dst->debug_level = atoi(level); 125 return 0; 126 } 127 dst = dst->next; 128 } 129 130 return -1; 131} 132 133 134static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 135 const char *txtaddr) 136{ 137 u8 addr[ETH_ALEN]; 138 struct sta_info *sta; 139 140 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 141 142 if (hwaddr_aton(txtaddr, addr)) 143 return -1; 144 145 sta = ap_get_sta(hapd, addr); 146 if (sta) 147 return 0; 148 149 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 150 "notification", MAC2STR(addr)); 151 sta = ap_sta_add(hapd, addr); 152 if (sta == NULL) 153 return -1; 154 155 hostapd_new_assoc_sta(hapd, sta, 0); 156 return 0; 157} 158 159 160#ifdef CONFIG_IEEE80211W 161#ifdef NEED_AP_MLME 162static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 163 const char *txtaddr) 164{ 165 u8 addr[ETH_ALEN]; 166 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 167 168 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 169 170 if (hwaddr_aton(txtaddr, addr) || 171 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 172 return -1; 173 174 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 175 176 return 0; 177} 178#endif /* NEED_AP_MLME */ 179#endif /* CONFIG_IEEE80211W */ 180 181 182#ifdef CONFIG_WPS 183static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 184{ 185 char *pin = os_strchr(txt, ' '); 186 char *timeout_txt; 187 int timeout; 188 u8 addr_buf[ETH_ALEN], *addr = NULL; 189 char *pos; 190 191 if (pin == NULL) 192 return -1; 193 *pin++ = '\0'; 194 195 timeout_txt = os_strchr(pin, ' '); 196 if (timeout_txt) { 197 *timeout_txt++ = '\0'; 198 timeout = atoi(timeout_txt); 199 pos = os_strchr(timeout_txt, ' '); 200 if (pos) { 201 *pos++ = '\0'; 202 if (hwaddr_aton(pos, addr_buf) == 0) 203 addr = addr_buf; 204 } 205 } else 206 timeout = 0; 207 208 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 209} 210 211 212static int hostapd_ctrl_iface_wps_check_pin( 213 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 214{ 215 char pin[9]; 216 size_t len; 217 char *pos; 218 int ret; 219 220 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 221 (u8 *) cmd, os_strlen(cmd)); 222 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 223 if (*pos < '0' || *pos > '9') 224 continue; 225 pin[len++] = *pos; 226 if (len == 9) { 227 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 228 return -1; 229 } 230 } 231 if (len != 4 && len != 8) { 232 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 233 return -1; 234 } 235 pin[len] = '\0'; 236 237 if (len == 8) { 238 unsigned int pin_val; 239 pin_val = atoi(pin); 240 if (!wps_pin_valid(pin_val)) { 241 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 242 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 243 if (ret < 0 || (size_t) ret >= buflen) 244 return -1; 245 return ret; 246 } 247 } 248 249 ret = os_snprintf(buf, buflen, "%s", pin); 250 if (ret < 0 || (size_t) ret >= buflen) 251 return -1; 252 253 return ret; 254} 255 256 257#ifdef CONFIG_WPS_NFC 258static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 259 char *pos) 260{ 261 size_t len; 262 struct wpabuf *buf; 263 int ret; 264 265 len = os_strlen(pos); 266 if (len & 0x01) 267 return -1; 268 len /= 2; 269 270 buf = wpabuf_alloc(len); 271 if (buf == NULL) 272 return -1; 273 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 274 wpabuf_free(buf); 275 return -1; 276 } 277 278 ret = hostapd_wps_nfc_tag_read(hapd, buf); 279 wpabuf_free(buf); 280 281 return ret; 282} 283 284 285static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 286 char *cmd, char *reply, 287 size_t max_len) 288{ 289 int ndef; 290 struct wpabuf *buf; 291 int res; 292 293 if (os_strcmp(cmd, "WPS") == 0) 294 ndef = 0; 295 else if (os_strcmp(cmd, "NDEF") == 0) 296 ndef = 1; 297 else 298 return -1; 299 300 buf = hostapd_wps_nfc_config_token(hapd, ndef); 301 if (buf == NULL) 302 return -1; 303 304 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 305 wpabuf_len(buf)); 306 reply[res++] = '\n'; 307 reply[res] = '\0'; 308 309 wpabuf_free(buf); 310 311 return res; 312} 313 314 315static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 316 char *reply, size_t max_len, 317 int ndef) 318{ 319 struct wpabuf *buf; 320 int res; 321 322 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 323 if (buf == NULL) 324 return -1; 325 326 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 327 wpabuf_len(buf)); 328 reply[res++] = '\n'; 329 reply[res] = '\0'; 330 331 wpabuf_free(buf); 332 333 return res; 334} 335 336 337static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 338 char *cmd, char *reply, 339 size_t max_len) 340{ 341 if (os_strcmp(cmd, "WPS") == 0) 342 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 343 max_len, 0); 344 345 if (os_strcmp(cmd, "NDEF") == 0) 346 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 347 max_len, 1); 348 349 if (os_strcmp(cmd, "enable") == 0) 350 return hostapd_wps_nfc_token_enable(hapd); 351 352 if (os_strcmp(cmd, "disable") == 0) { 353 hostapd_wps_nfc_token_disable(hapd); 354 return 0; 355 } 356 357 return -1; 358} 359 360 361static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 362 char *cmd, char *reply, 363 size_t max_len) 364{ 365 struct wpabuf *buf; 366 int res; 367 char *pos; 368 int ndef; 369 370 pos = os_strchr(cmd, ' '); 371 if (pos == NULL) 372 return -1; 373 *pos++ = '\0'; 374 375 if (os_strcmp(cmd, "WPS") == 0) 376 ndef = 0; 377 else if (os_strcmp(cmd, "NDEF") == 0) 378 ndef = 1; 379 else 380 return -1; 381 382 if (os_strcmp(pos, "WPS-CR") == 0) 383 buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 384 else 385 buf = NULL; 386 if (buf == NULL) 387 return -1; 388 389 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 390 wpabuf_len(buf)); 391 reply[res++] = '\n'; 392 reply[res] = '\0'; 393 394 wpabuf_free(buf); 395 396 return res; 397} 398 399 400static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 401 char *cmd) 402{ 403 size_t len; 404 struct wpabuf *req, *sel; 405 int ret; 406 char *pos, *role, *type, *pos2; 407 408 role = cmd; 409 pos = os_strchr(role, ' '); 410 if (pos == NULL) 411 return -1; 412 *pos++ = '\0'; 413 414 type = pos; 415 pos = os_strchr(type, ' '); 416 if (pos == NULL) 417 return -1; 418 *pos++ = '\0'; 419 420 pos2 = os_strchr(pos, ' '); 421 if (pos2 == NULL) 422 return -1; 423 *pos2++ = '\0'; 424 425 len = os_strlen(pos); 426 if (len & 0x01) 427 return -1; 428 len /= 2; 429 430 req = wpabuf_alloc(len); 431 if (req == NULL) 432 return -1; 433 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 434 wpabuf_free(req); 435 return -1; 436 } 437 438 len = os_strlen(pos2); 439 if (len & 0x01) { 440 wpabuf_free(req); 441 return -1; 442 } 443 len /= 2; 444 445 sel = wpabuf_alloc(len); 446 if (sel == NULL) { 447 wpabuf_free(req); 448 return -1; 449 } 450 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 451 wpabuf_free(req); 452 wpabuf_free(sel); 453 return -1; 454 } 455 456 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 457 ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 458 } else { 459 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 460 "reported: role=%s type=%s", role, type); 461 ret = -1; 462 } 463 wpabuf_free(req); 464 wpabuf_free(sel); 465 466 return ret; 467} 468 469#endif /* CONFIG_WPS_NFC */ 470 471 472static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 473 char *buf, size_t buflen) 474{ 475 int timeout = 300; 476 char *pos; 477 const char *pin_txt; 478 479 pos = os_strchr(txt, ' '); 480 if (pos) 481 *pos++ = '\0'; 482 483 if (os_strcmp(txt, "disable") == 0) { 484 hostapd_wps_ap_pin_disable(hapd); 485 return os_snprintf(buf, buflen, "OK\n"); 486 } 487 488 if (os_strcmp(txt, "random") == 0) { 489 if (pos) 490 timeout = atoi(pos); 491 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 492 if (pin_txt == NULL) 493 return -1; 494 return os_snprintf(buf, buflen, "%s", pin_txt); 495 } 496 497 if (os_strcmp(txt, "get") == 0) { 498 pin_txt = hostapd_wps_ap_pin_get(hapd); 499 if (pin_txt == NULL) 500 return -1; 501 return os_snprintf(buf, buflen, "%s", pin_txt); 502 } 503 504 if (os_strcmp(txt, "set") == 0) { 505 char *pin; 506 if (pos == NULL) 507 return -1; 508 pin = pos; 509 pos = os_strchr(pos, ' '); 510 if (pos) { 511 *pos++ = '\0'; 512 timeout = atoi(pos); 513 } 514 if (os_strlen(pin) > buflen) 515 return -1; 516 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 517 return -1; 518 return os_snprintf(buf, buflen, "%s", pin); 519 } 520 521 return -1; 522} 523 524 525static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 526{ 527 char *pos; 528 char *ssid, *auth, *encr = NULL, *key = NULL; 529 530 ssid = txt; 531 pos = os_strchr(txt, ' '); 532 if (!pos) 533 return -1; 534 *pos++ = '\0'; 535 536 auth = pos; 537 pos = os_strchr(pos, ' '); 538 if (pos) { 539 *pos++ = '\0'; 540 encr = pos; 541 pos = os_strchr(pos, ' '); 542 if (pos) { 543 *pos++ = '\0'; 544 key = pos; 545 } 546 } 547 548 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 549} 550 551 552static const char * pbc_status_str(enum pbc_status status) 553{ 554 switch (status) { 555 case WPS_PBC_STATUS_DISABLE: 556 return "Disabled"; 557 case WPS_PBC_STATUS_ACTIVE: 558 return "Active"; 559 case WPS_PBC_STATUS_TIMEOUT: 560 return "Timed-out"; 561 case WPS_PBC_STATUS_OVERLAP: 562 return "Overlap"; 563 default: 564 return "Unknown"; 565 } 566} 567 568 569static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd, 570 char *buf, size_t buflen) 571{ 572 int ret; 573 char *pos, *end; 574 575 pos = buf; 576 end = buf + buflen; 577 578 ret = os_snprintf(pos, end - pos, "PBC Status: %s\n", 579 pbc_status_str(hapd->wps_stats.pbc_status)); 580 581 if (ret < 0 || ret >= end - pos) 582 return pos - buf; 583 pos += ret; 584 585 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 586 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 587 "Success": 588 (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 589 "Failed" : "None"))); 590 591 if (ret < 0 || ret >= end - pos) 592 return pos - buf; 593 pos += ret; 594 595 /* If status == Failure - Add possible Reasons */ 596 if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 597 hapd->wps_stats.failure_reason > 0) { 598 ret = os_snprintf(pos, end - pos, 599 "Failure Reason: %s\n", 600 wps_ei_str(hapd->wps_stats.failure_reason)); 601 602 if (ret < 0 || ret >= end - pos) 603 return pos - buf; 604 pos += ret; 605 } 606 607 if (hapd->wps_stats.status) { 608 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 609 MAC2STR(hapd->wps_stats.peer_addr)); 610 611 if (ret < 0 || ret >= end - pos) 612 return pos - buf; 613 pos += ret; 614 } 615 616 return pos - buf; 617} 618 619#endif /* CONFIG_WPS */ 620 621#ifdef CONFIG_HS20 622 623static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 624 const char *cmd) 625{ 626 u8 addr[ETH_ALEN]; 627 const char *url; 628 629 if (hwaddr_aton(cmd, addr)) 630 return -1; 631 url = cmd + 17; 632 if (*url == '\0') { 633 url = NULL; 634 } else { 635 if (*url != ' ') 636 return -1; 637 url++; 638 if (*url == '\0') 639 url = NULL; 640 } 641 642 return hs20_send_wnm_notification(hapd, addr, 1, url); 643} 644 645 646static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 647 const char *cmd) 648{ 649 u8 addr[ETH_ALEN]; 650 int code, reauth_delay, ret; 651 const char *pos; 652 size_t url_len; 653 struct wpabuf *req; 654 655 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 656 if (hwaddr_aton(cmd, addr)) 657 return -1; 658 659 pos = os_strchr(cmd, ' '); 660 if (pos == NULL) 661 return -1; 662 pos++; 663 code = atoi(pos); 664 665 pos = os_strchr(pos, ' '); 666 if (pos == NULL) 667 return -1; 668 pos++; 669 reauth_delay = atoi(pos); 670 671 url_len = 0; 672 pos = os_strchr(pos, ' '); 673 if (pos) { 674 pos++; 675 url_len = os_strlen(pos); 676 } 677 678 req = wpabuf_alloc(4 + url_len); 679 if (req == NULL) 680 return -1; 681 wpabuf_put_u8(req, code); 682 wpabuf_put_le16(req, reauth_delay); 683 wpabuf_put_u8(req, url_len); 684 if (pos) 685 wpabuf_put_data(req, pos, url_len); 686 687 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 688 " to indicate imminent deauthentication (code=%d " 689 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 690 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 691 wpabuf_free(req); 692 return ret; 693} 694 695#endif /* CONFIG_HS20 */ 696 697 698#ifdef CONFIG_INTERWORKING 699 700static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 701 const char *cmd) 702{ 703 u8 qos_map_set[16 + 2 * 21], count = 0; 704 const char *pos = cmd; 705 int val, ret; 706 707 for (;;) { 708 if (count == sizeof(qos_map_set)) { 709 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 710 return -1; 711 } 712 713 val = atoi(pos); 714 if (val < 0 || val > 255) { 715 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 716 return -1; 717 } 718 719 qos_map_set[count++] = val; 720 pos = os_strchr(pos, ','); 721 if (!pos) 722 break; 723 pos++; 724 } 725 726 if (count < 16 || count & 1) { 727 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 728 return -1; 729 } 730 731 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 732 if (ret) { 733 wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 734 return -1; 735 } 736 737 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 738 hapd->conf->qos_map_set_len = count; 739 740 return 0; 741} 742 743 744static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 745 const char *cmd) 746{ 747 u8 addr[ETH_ALEN]; 748 struct sta_info *sta; 749 struct wpabuf *buf; 750 u8 *qos_map_set = hapd->conf->qos_map_set; 751 u8 qos_map_set_len = hapd->conf->qos_map_set_len; 752 int ret; 753 754 if (!qos_map_set_len) { 755 wpa_printf(MSG_INFO, "QoS Map Set is not set"); 756 return -1; 757 } 758 759 if (hwaddr_aton(cmd, addr)) 760 return -1; 761 762 sta = ap_get_sta(hapd, addr); 763 if (sta == NULL) { 764 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 765 "for QoS Map Configuration message", 766 MAC2STR(addr)); 767 return -1; 768 } 769 770 if (!sta->qos_map_enabled) { 771 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 772 "support for QoS Map", MAC2STR(addr)); 773 return -1; 774 } 775 776 buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 777 if (buf == NULL) 778 return -1; 779 780 wpabuf_put_u8(buf, WLAN_ACTION_QOS); 781 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 782 783 /* QoS Map Set Element */ 784 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 785 wpabuf_put_u8(buf, qos_map_set_len); 786 wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 787 788 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 789 wpabuf_head(buf), wpabuf_len(buf)); 790 wpabuf_free(buf); 791 792 return ret; 793} 794 795#endif /* CONFIG_INTERWORKING */ 796 797 798#ifdef CONFIG_WNM 799 800static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 801 const char *cmd) 802{ 803 u8 addr[ETH_ALEN]; 804 int disassoc_timer; 805 struct sta_info *sta; 806 807 if (hwaddr_aton(cmd, addr)) 808 return -1; 809 if (cmd[17] != ' ') 810 return -1; 811 disassoc_timer = atoi(cmd + 17); 812 813 sta = ap_get_sta(hapd, addr); 814 if (sta == NULL) { 815 wpa_printf(MSG_DEBUG, "Station " MACSTR 816 " not found for disassociation imminent message", 817 MAC2STR(addr)); 818 return -1; 819 } 820 821 return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); 822} 823 824 825static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 826 const char *cmd) 827{ 828 u8 addr[ETH_ALEN]; 829 const char *url, *timerstr; 830 int disassoc_timer; 831 struct sta_info *sta; 832 833 if (hwaddr_aton(cmd, addr)) 834 return -1; 835 836 sta = ap_get_sta(hapd, addr); 837 if (sta == NULL) { 838 wpa_printf(MSG_DEBUG, "Station " MACSTR 839 " not found for ESS disassociation imminent message", 840 MAC2STR(addr)); 841 return -1; 842 } 843 844 timerstr = cmd + 17; 845 if (*timerstr != ' ') 846 return -1; 847 timerstr++; 848 disassoc_timer = atoi(timerstr); 849 if (disassoc_timer < 0 || disassoc_timer > 65535) 850 return -1; 851 852 url = os_strchr(timerstr, ' '); 853 if (url == NULL) 854 return -1; 855 url++; 856 857 return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); 858} 859 860#endif /* CONFIG_WNM */ 861 862 863static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 864 char *buf, size_t buflen) 865{ 866 int ret; 867 char *pos, *end; 868 869 pos = buf; 870 end = buf + buflen; 871 872 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 873 "ssid=%s\n", 874 MAC2STR(hapd->own_addr), 875 wpa_ssid_txt(hapd->conf->ssid.ssid, 876 hapd->conf->ssid.ssid_len)); 877 if (ret < 0 || ret >= end - pos) 878 return pos - buf; 879 pos += ret; 880 881#ifdef CONFIG_WPS 882 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 883 hapd->conf->wps_state == 0 ? "disabled" : 884 (hapd->conf->wps_state == 1 ? "not configured" : 885 "configured")); 886 if (ret < 0 || ret >= end - pos) 887 return pos - buf; 888 pos += ret; 889 890 if (hapd->conf->wps_state && hapd->conf->wpa && 891 hapd->conf->ssid.wpa_passphrase) { 892 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 893 hapd->conf->ssid.wpa_passphrase); 894 if (ret < 0 || ret >= end - pos) 895 return pos - buf; 896 pos += ret; 897 } 898 899 if (hapd->conf->wps_state && hapd->conf->wpa && 900 hapd->conf->ssid.wpa_psk && 901 hapd->conf->ssid.wpa_psk->group) { 902 char hex[PMK_LEN * 2 + 1]; 903 wpa_snprintf_hex(hex, sizeof(hex), 904 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 905 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 906 if (ret < 0 || ret >= end - pos) 907 return pos - buf; 908 pos += ret; 909 } 910#endif /* CONFIG_WPS */ 911 912 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 913 ret = os_snprintf(pos, end - pos, "key_mgmt="); 914 if (ret < 0 || ret >= end - pos) 915 return pos - buf; 916 pos += ret; 917 918 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 919 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 920 if (ret < 0 || ret >= end - pos) 921 return pos - buf; 922 pos += ret; 923 } 924 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 925 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 926 if (ret < 0 || ret >= end - pos) 927 return pos - buf; 928 pos += ret; 929 } 930#ifdef CONFIG_IEEE80211R 931 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 932 ret = os_snprintf(pos, end - pos, "FT-PSK "); 933 if (ret < 0 || ret >= end - pos) 934 return pos - buf; 935 pos += ret; 936 } 937 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 938 ret = os_snprintf(pos, end - pos, "FT-EAP "); 939 if (ret < 0 || ret >= end - pos) 940 return pos - buf; 941 pos += ret; 942 } 943#ifdef CONFIG_SAE 944 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 945 ret = os_snprintf(pos, end - pos, "FT-SAE "); 946 if (ret < 0 || ret >= end - pos) 947 return pos - buf; 948 pos += ret; 949 } 950#endif /* CONFIG_SAE */ 951#endif /* CONFIG_IEEE80211R */ 952#ifdef CONFIG_IEEE80211W 953 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 954 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 955 if (ret < 0 || ret >= end - pos) 956 return pos - buf; 957 pos += ret; 958 } 959 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 960 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 961 if (ret < 0 || ret >= end - pos) 962 return pos - buf; 963 pos += ret; 964 } 965#endif /* CONFIG_IEEE80211W */ 966#ifdef CONFIG_SAE 967 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 968 ret = os_snprintf(pos, end - pos, "SAE "); 969 if (ret < 0 || ret >= end - pos) 970 return pos - buf; 971 pos += ret; 972 } 973#endif /* CONFIG_SAE */ 974 975 ret = os_snprintf(pos, end - pos, "\n"); 976 if (ret < 0 || ret >= end - pos) 977 return pos - buf; 978 pos += ret; 979 } 980 981 if (hapd->conf->wpa) { 982 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 983 wpa_cipher_txt(hapd->conf->wpa_group)); 984 if (ret < 0 || ret >= end - pos) 985 return pos - buf; 986 pos += ret; 987 } 988 989 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 990 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 991 if (ret < 0 || ret >= end - pos) 992 return pos - buf; 993 pos += ret; 994 995 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 996 " "); 997 if (ret < 0) 998 return pos - buf; 999 pos += ret; 1000 1001 ret = os_snprintf(pos, end - pos, "\n"); 1002 if (ret < 0 || ret >= end - pos) 1003 return pos - buf; 1004 pos += ret; 1005 } 1006 1007 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1008 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1009 if (ret < 0 || ret >= end - pos) 1010 return pos - buf; 1011 pos += ret; 1012 1013 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1014 " "); 1015 if (ret < 0) 1016 return pos - buf; 1017 pos += ret; 1018 1019 ret = os_snprintf(pos, end - pos, "\n"); 1020 if (ret < 0 || ret >= end - pos) 1021 return pos - buf; 1022 pos += ret; 1023 } 1024 1025 return pos - buf; 1026} 1027 1028 1029static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1030{ 1031 char *value; 1032 int ret = 0; 1033 1034 value = os_strchr(cmd, ' '); 1035 if (value == NULL) 1036 return -1; 1037 *value++ = '\0'; 1038 1039 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1040 if (0) { 1041#ifdef CONFIG_WPS_TESTING 1042 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1043 long int val; 1044 val = strtol(value, NULL, 0); 1045 if (val < 0 || val > 0xff) { 1046 ret = -1; 1047 wpa_printf(MSG_DEBUG, "WPS: Invalid " 1048 "wps_version_number %ld", val); 1049 } else { 1050 wps_version_number = val; 1051 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1052 "version %u.%u", 1053 (wps_version_number & 0xf0) >> 4, 1054 wps_version_number & 0x0f); 1055 hostapd_wps_update_ie(hapd); 1056 } 1057 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 1058 wps_testing_dummy_cred = atoi(value); 1059 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 1060 wps_testing_dummy_cred); 1061 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1062 wps_corrupt_pkhash = atoi(value); 1063 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1064 wps_corrupt_pkhash); 1065#endif /* CONFIG_WPS_TESTING */ 1066#ifdef CONFIG_INTERWORKING 1067 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) { 1068 int val = atoi(value); 1069 if (val <= 0) 1070 ret = -1; 1071 else 1072 hapd->gas_frag_limit = val; 1073#endif /* CONFIG_INTERWORKING */ 1074#ifdef CONFIG_TESTING_OPTIONS 1075 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1076 hapd->ext_mgmt_frame_handling = atoi(value); 1077#endif /* CONFIG_TESTING_OPTIONS */ 1078 } else { 1079 struct sta_info *sta; 1080 int vlan_id; 1081 1082 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1083 if (ret) 1084 return ret; 1085 1086 if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1087 for (sta = hapd->sta_list; sta; sta = sta->next) { 1088 if (hostapd_maclist_found( 1089 hapd->conf->deny_mac, 1090 hapd->conf->num_deny_mac, sta->addr, 1091 &vlan_id) && 1092 (!vlan_id || vlan_id == sta->vlan_id)) 1093 ap_sta_disconnect( 1094 hapd, sta, sta->addr, 1095 WLAN_REASON_UNSPECIFIED); 1096 } 1097 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED && 1098 os_strcasecmp(cmd, "accept_mac_file") == 0) { 1099 for (sta = hapd->sta_list; sta; sta = sta->next) { 1100 if (!hostapd_maclist_found( 1101 hapd->conf->accept_mac, 1102 hapd->conf->num_accept_mac, 1103 sta->addr, &vlan_id) || 1104 (vlan_id && vlan_id != sta->vlan_id)) 1105 ap_sta_disconnect( 1106 hapd, sta, sta->addr, 1107 WLAN_REASON_UNSPECIFIED); 1108 } 1109 } 1110 } 1111 1112 return ret; 1113} 1114 1115 1116static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1117 char *buf, size_t buflen) 1118{ 1119 int res; 1120 1121 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1122 1123 if (os_strcmp(cmd, "version") == 0) { 1124 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1125 if (res < 0 || (unsigned int) res >= buflen) 1126 return -1; 1127 return res; 1128 } 1129 1130 return -1; 1131} 1132 1133 1134static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1135{ 1136 if (hostapd_enable_iface(iface) < 0) { 1137 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1138 return -1; 1139 } 1140 return 0; 1141} 1142 1143 1144static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1145{ 1146 if (hostapd_reload_iface(iface) < 0) { 1147 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1148 return -1; 1149 } 1150 return 0; 1151} 1152 1153 1154static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1155{ 1156 if (hostapd_disable_iface(iface) < 0) { 1157 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1158 return -1; 1159 } 1160 return 0; 1161} 1162 1163 1164#ifdef CONFIG_TESTING_OPTIONS 1165 1166static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1167{ 1168 union wpa_event_data data; 1169 char *pos, *param; 1170 enum wpa_event_type event; 1171 1172 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1173 1174 os_memset(&data, 0, sizeof(data)); 1175 1176 param = os_strchr(cmd, ' '); 1177 if (param == NULL) 1178 return -1; 1179 *param++ = '\0'; 1180 1181 if (os_strcmp(cmd, "DETECTED") == 0) 1182 event = EVENT_DFS_RADAR_DETECTED; 1183 else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1184 event = EVENT_DFS_CAC_FINISHED; 1185 else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1186 event = EVENT_DFS_CAC_ABORTED; 1187 else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1188 event = EVENT_DFS_NOP_FINISHED; 1189 else { 1190 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1191 cmd); 1192 return -1; 1193 } 1194 1195 pos = os_strstr(param, "freq="); 1196 if (pos) 1197 data.dfs_event.freq = atoi(pos + 5); 1198 1199 pos = os_strstr(param, "ht_enabled=1"); 1200 if (pos) 1201 data.dfs_event.ht_enabled = 1; 1202 1203 pos = os_strstr(param, "chan_offset="); 1204 if (pos) 1205 data.dfs_event.chan_offset = atoi(pos + 12); 1206 1207 pos = os_strstr(param, "chan_width="); 1208 if (pos) 1209 data.dfs_event.chan_width = atoi(pos + 11); 1210 1211 pos = os_strstr(param, "cf1="); 1212 if (pos) 1213 data.dfs_event.cf1 = atoi(pos + 4); 1214 1215 pos = os_strstr(param, "cf2="); 1216 if (pos) 1217 data.dfs_event.cf2 = atoi(pos + 4); 1218 1219 wpa_supplicant_event(hapd, event, &data); 1220 1221 return 0; 1222} 1223 1224 1225static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1226{ 1227 size_t len; 1228 u8 *buf; 1229 int res; 1230 1231 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1232 1233 len = os_strlen(cmd); 1234 if (len & 1) 1235 return -1; 1236 len /= 2; 1237 1238 buf = os_malloc(len); 1239 if (buf == NULL) 1240 return -1; 1241 1242 if (hexstr2bin(cmd, buf, len) < 0) { 1243 os_free(buf); 1244 return -1; 1245 } 1246 1247 res = hostapd_drv_send_mlme(hapd, buf, len, 0); 1248 os_free(buf); 1249 return res; 1250} 1251 1252#endif /* CONFIG_TESTING_OPTIONS */ 1253 1254 1255static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 1256 char *pos) 1257{ 1258#ifdef NEED_AP_MLME 1259 struct csa_settings settings; 1260 int ret; 1261 unsigned int i; 1262 1263 ret = hostapd_parse_csa_settings(pos, &settings); 1264 if (ret) 1265 return ret; 1266 1267 for (i = 0; i < iface->num_bss; i++) { 1268 ret = hostapd_switch_channel(iface->bss[i], &settings); 1269 if (ret) { 1270 /* FIX: What do we do if CSA fails in the middle of 1271 * submitting multi-BSS CSA requests? */ 1272 return ret; 1273 } 1274 } 1275 1276 return 0; 1277#else /* NEED_AP_MLME */ 1278 return -1; 1279#endif /* NEED_AP_MLME */ 1280} 1281 1282 1283static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 1284 int reply_size, const char *param) 1285{ 1286#ifdef RADIUS_SERVER 1287 if (os_strcmp(param, "radius_server") == 0) { 1288 return radius_server_get_mib(hapd->radius_srv, reply, 1289 reply_size); 1290 } 1291#endif /* RADIUS_SERVER */ 1292 return -1; 1293} 1294 1295 1296static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 1297 char *buf, size_t buflen) 1298{ 1299 int ret; 1300 char *pos; 1301 u8 *data = NULL; 1302 unsigned int vendor_id, subcmd; 1303 struct wpabuf *reply; 1304 size_t data_len = 0; 1305 1306 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 1307 vendor_id = strtoul(cmd, &pos, 16); 1308 if (!isblank(*pos)) 1309 return -EINVAL; 1310 1311 subcmd = strtoul(pos, &pos, 10); 1312 1313 if (*pos != '\0') { 1314 if (!isblank(*pos++)) 1315 return -EINVAL; 1316 data_len = os_strlen(pos); 1317 } 1318 1319 if (data_len) { 1320 data_len /= 2; 1321 data = os_malloc(data_len); 1322 if (!data) 1323 return -ENOBUFS; 1324 1325 if (hexstr2bin(pos, data, data_len)) { 1326 wpa_printf(MSG_DEBUG, 1327 "Vendor command: wrong parameter format"); 1328 os_free(data); 1329 return -EINVAL; 1330 } 1331 } 1332 1333 reply = wpabuf_alloc((buflen - 1) / 2); 1334 if (!reply) { 1335 os_free(data); 1336 return -ENOBUFS; 1337 } 1338 1339 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 1340 reply); 1341 1342 if (ret == 0) 1343 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 1344 wpabuf_len(reply)); 1345 1346 wpabuf_free(reply); 1347 os_free(data); 1348 1349 return ret; 1350} 1351 1352 1353static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 1354 void *sock_ctx) 1355{ 1356 struct hostapd_data *hapd = eloop_ctx; 1357 char buf[4096]; 1358 int res; 1359 struct sockaddr_un from; 1360 socklen_t fromlen = sizeof(from); 1361 char *reply; 1362 const int reply_size = 4096; 1363 int reply_len; 1364 int level = MSG_DEBUG; 1365 1366 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1367 (struct sockaddr *) &from, &fromlen); 1368 if (res < 0) { 1369 perror("recvfrom(ctrl_iface)"); 1370 return; 1371 } 1372 buf[res] = '\0'; 1373 if (os_strcmp(buf, "PING") == 0) 1374 level = MSG_EXCESSIVE; 1375 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 1376 1377 reply = os_malloc(reply_size); 1378 if (reply == NULL) { 1379 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 1380 fromlen); 1381 return; 1382 } 1383 1384 os_memcpy(reply, "OK\n", 3); 1385 reply_len = 3; 1386 1387 if (os_strcmp(buf, "PING") == 0) { 1388 os_memcpy(reply, "PONG\n", 5); 1389 reply_len = 5; 1390 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 1391 if (wpa_debug_reopen_file() < 0) 1392 reply_len = -1; 1393 } else if (os_strcmp(buf, "STATUS") == 0) { 1394 reply_len = hostapd_ctrl_iface_status(hapd, reply, 1395 reply_size); 1396 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 1397 reply_len = hostapd_drv_status(hapd, reply, reply_size); 1398 } else if (os_strcmp(buf, "MIB") == 0) { 1399 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 1400 if (reply_len >= 0) { 1401 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 1402 reply_size - reply_len); 1403 if (res < 0) 1404 reply_len = -1; 1405 else 1406 reply_len += res; 1407 } 1408 if (reply_len >= 0) { 1409 res = ieee802_1x_get_mib(hapd, reply + reply_len, 1410 reply_size - reply_len); 1411 if (res < 0) 1412 reply_len = -1; 1413 else 1414 reply_len += res; 1415 } 1416#ifndef CONFIG_NO_RADIUS 1417 if (reply_len >= 0) { 1418 res = radius_client_get_mib(hapd->radius, 1419 reply + reply_len, 1420 reply_size - reply_len); 1421 if (res < 0) 1422 reply_len = -1; 1423 else 1424 reply_len += res; 1425 } 1426#endif /* CONFIG_NO_RADIUS */ 1427 } else if (os_strncmp(buf, "MIB ", 4) == 0) { 1428 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 1429 buf + 4); 1430 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 1431 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 1432 reply_size); 1433 } else if (os_strncmp(buf, "STA ", 4) == 0) { 1434 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 1435 reply_size); 1436 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 1437 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 1438 reply_size); 1439 } else if (os_strcmp(buf, "ATTACH") == 0) { 1440 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 1441 reply_len = -1; 1442 } else if (os_strcmp(buf, "DETACH") == 0) { 1443 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 1444 reply_len = -1; 1445 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 1446 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 1447 buf + 6)) 1448 reply_len = -1; 1449 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 1450 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 1451 reply_len = -1; 1452 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 1453 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 1454 reply_len = -1; 1455 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 1456 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 1457 reply_len = -1; 1458#ifdef CONFIG_IEEE80211W 1459#ifdef NEED_AP_MLME 1460 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 1461 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 1462 reply_len = -1; 1463#endif /* NEED_AP_MLME */ 1464#endif /* CONFIG_IEEE80211W */ 1465#ifdef CONFIG_WPS 1466 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1467 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 1468 reply_len = -1; 1469 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 1470 reply_len = hostapd_ctrl_iface_wps_check_pin( 1471 hapd, buf + 14, reply, reply_size); 1472 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1473 if (hostapd_wps_button_pushed(hapd, NULL)) 1474 reply_len = -1; 1475 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 1476 if (hostapd_wps_cancel(hapd)) 1477 reply_len = -1; 1478 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 1479 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 1480 reply, reply_size); 1481 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 1482 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 1483 reply_len = -1; 1484 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 1485 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 1486 reply_size); 1487#ifdef CONFIG_WPS_NFC 1488 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 1489 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 1490 reply_len = -1; 1491 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 1492 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 1493 hapd, buf + 21, reply, reply_size); 1494 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 1495 reply_len = hostapd_ctrl_iface_wps_nfc_token( 1496 hapd, buf + 14, reply, reply_size); 1497 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 1498 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 1499 hapd, buf + 21, reply, reply_size); 1500 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 1501 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 1502 reply_len = -1; 1503#endif /* CONFIG_WPS_NFC */ 1504#endif /* CONFIG_WPS */ 1505#ifdef CONFIG_INTERWORKING 1506 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 1507 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 1508 reply_len = -1; 1509 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 1510 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 1511 reply_len = -1; 1512#endif /* CONFIG_INTERWORKING */ 1513#ifdef CONFIG_HS20 1514 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 1515 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 1516 reply_len = -1; 1517 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 1518 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 1519 reply_len = -1; 1520#endif /* CONFIG_HS20 */ 1521#ifdef CONFIG_WNM 1522 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 1523 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 1524 reply_len = -1; 1525 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 1526 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 1527 reply_len = -1; 1528#endif /* CONFIG_WNM */ 1529 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 1530 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 1531 reply_size); 1532 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1533 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 1534 reply_len = -1; 1535 } else if (os_strncmp(buf, "GET ", 4) == 0) { 1536 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 1537 reply_size); 1538 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 1539 if (hostapd_ctrl_iface_enable(hapd->iface)) 1540 reply_len = -1; 1541 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 1542 if (hostapd_ctrl_iface_reload(hapd->iface)) 1543 reply_len = -1; 1544 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 1545 if (hostapd_ctrl_iface_disable(hapd->iface)) 1546 reply_len = -1; 1547#ifdef CONFIG_TESTING_OPTIONS 1548 } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 1549 if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 1550 reply_len = -1; 1551 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 1552 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 1553 reply_len = -1; 1554#endif /* CONFIG_TESTING_OPTIONS */ 1555 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 1556 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 1557 reply_len = -1; 1558 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 1559 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 1560 reply_size); 1561 1562 } else { 1563 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1564 reply_len = 16; 1565 } 1566 1567 if (reply_len < 0) { 1568 os_memcpy(reply, "FAIL\n", 5); 1569 reply_len = 5; 1570 } 1571 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 1572 os_free(reply); 1573} 1574 1575 1576static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 1577{ 1578 char *buf; 1579 size_t len; 1580 1581 if (hapd->conf->ctrl_interface == NULL) 1582 return NULL; 1583 1584 len = os_strlen(hapd->conf->ctrl_interface) + 1585 os_strlen(hapd->conf->iface) + 2; 1586 buf = os_malloc(len); 1587 if (buf == NULL) 1588 return NULL; 1589 1590 os_snprintf(buf, len, "%s/%s", 1591 hapd->conf->ctrl_interface, hapd->conf->iface); 1592 buf[len - 1] = '\0'; 1593 return buf; 1594} 1595 1596 1597static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global, 1598 const char *txt, size_t len) 1599{ 1600 struct hostapd_data *hapd = ctx; 1601 if (hapd == NULL) 1602 return; 1603 hostapd_ctrl_iface_send(hapd, level, txt, len); 1604} 1605 1606 1607int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 1608{ 1609 struct sockaddr_un addr; 1610 int s = -1; 1611 char *fname = NULL; 1612 1613 if (hapd->ctrl_sock > -1) { 1614 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 1615 return 0; 1616 } 1617 1618 if (hapd->conf->ctrl_interface == NULL) 1619 return 0; 1620 1621 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 1622 if (errno == EEXIST) { 1623 wpa_printf(MSG_DEBUG, "Using existing control " 1624 "interface directory."); 1625 } else { 1626 perror("mkdir[ctrl_interface]"); 1627 goto fail; 1628 } 1629 } 1630 1631 if (hapd->conf->ctrl_interface_gid_set && 1632 chown(hapd->conf->ctrl_interface, -1, 1633 hapd->conf->ctrl_interface_gid) < 0) { 1634 perror("chown[ctrl_interface]"); 1635 return -1; 1636 } 1637 1638 if (!hapd->conf->ctrl_interface_gid_set && 1639 hapd->iface->interfaces->ctrl_iface_group && 1640 chown(hapd->conf->ctrl_interface, -1, 1641 hapd->iface->interfaces->ctrl_iface_group) < 0) { 1642 perror("chown[ctrl_interface]"); 1643 return -1; 1644 } 1645 1646#ifdef ANDROID 1647 /* 1648 * Android is using umask 0077 which would leave the control interface 1649 * directory without group access. This breaks things since Wi-Fi 1650 * framework assumes that this directory can be accessed by other 1651 * applications in the wifi group. Fix this by adding group access even 1652 * if umask value would prevent this. 1653 */ 1654 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 1655 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 1656 strerror(errno)); 1657 /* Try to continue anyway */ 1658 } 1659#endif /* ANDROID */ 1660 1661 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 1662 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 1663 goto fail; 1664 1665 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1666 if (s < 0) { 1667 perror("socket(PF_UNIX)"); 1668 goto fail; 1669 } 1670 1671 os_memset(&addr, 0, sizeof(addr)); 1672#ifdef __FreeBSD__ 1673 addr.sun_len = sizeof(addr); 1674#endif /* __FreeBSD__ */ 1675 addr.sun_family = AF_UNIX; 1676 fname = hostapd_ctrl_iface_path(hapd); 1677 if (fname == NULL) 1678 goto fail; 1679 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1680 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1681 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1682 strerror(errno)); 1683 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1684 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1685 " allow connections - assuming it was left" 1686 "over from forced program termination"); 1687 if (unlink(fname) < 0) { 1688 perror("unlink[ctrl_iface]"); 1689 wpa_printf(MSG_ERROR, "Could not unlink " 1690 "existing ctrl_iface socket '%s'", 1691 fname); 1692 goto fail; 1693 } 1694 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1695 0) { 1696 perror("hostapd-ctrl-iface: bind(PF_UNIX)"); 1697 goto fail; 1698 } 1699 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1700 "ctrl_iface socket '%s'", fname); 1701 } else { 1702 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1703 "be in use - cannot override it"); 1704 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1705 "not used anymore", fname); 1706 os_free(fname); 1707 fname = NULL; 1708 goto fail; 1709 } 1710 } 1711 1712 if (hapd->conf->ctrl_interface_gid_set && 1713 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 1714 perror("chown[ctrl_interface/ifname]"); 1715 goto fail; 1716 } 1717 1718 if (!hapd->conf->ctrl_interface_gid_set && 1719 hapd->iface->interfaces->ctrl_iface_group && 1720 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 1721 perror("chown[ctrl_interface/ifname]"); 1722 goto fail; 1723 } 1724 1725 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1726 perror("chmod[ctrl_interface/ifname]"); 1727 goto fail; 1728 } 1729 os_free(fname); 1730 1731 hapd->ctrl_sock = s; 1732 eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 1733 NULL); 1734 hapd->msg_ctx = hapd; 1735 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 1736 1737 return 0; 1738 1739fail: 1740 if (s >= 0) 1741 close(s); 1742 if (fname) { 1743 unlink(fname); 1744 os_free(fname); 1745 } 1746 return -1; 1747} 1748 1749 1750void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 1751{ 1752 struct wpa_ctrl_dst *dst, *prev; 1753 1754 if (hapd->ctrl_sock > -1) { 1755 char *fname; 1756 eloop_unregister_read_sock(hapd->ctrl_sock); 1757 close(hapd->ctrl_sock); 1758 hapd->ctrl_sock = -1; 1759 fname = hostapd_ctrl_iface_path(hapd); 1760 if (fname) 1761 unlink(fname); 1762 os_free(fname); 1763 1764 if (hapd->conf->ctrl_interface && 1765 rmdir(hapd->conf->ctrl_interface) < 0) { 1766 if (errno == ENOTEMPTY) { 1767 wpa_printf(MSG_DEBUG, "Control interface " 1768 "directory not empty - leaving it " 1769 "behind"); 1770 } else { 1771 wpa_printf(MSG_ERROR, 1772 "rmdir[ctrl_interface=%s]: %s", 1773 hapd->conf->ctrl_interface, 1774 strerror(errno)); 1775 } 1776 } 1777 } 1778 1779 dst = hapd->ctrl_dst; 1780 while (dst) { 1781 prev = dst; 1782 dst = dst->next; 1783 os_free(prev); 1784 } 1785} 1786 1787 1788static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 1789 char *buf) 1790{ 1791 if (hostapd_add_iface(interfaces, buf) < 0) { 1792 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 1793 return -1; 1794 } 1795 return 0; 1796} 1797 1798 1799static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 1800 char *buf) 1801{ 1802 if (hostapd_remove_iface(interfaces, buf) < 0) { 1803 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 1804 return -1; 1805 } 1806 return 0; 1807} 1808 1809 1810static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 1811{ 1812#ifdef CONFIG_WPS_TESTING 1813 wps_version_number = 0x20; 1814 wps_testing_dummy_cred = 0; 1815 wps_corrupt_pkhash = 0; 1816#endif /* CONFIG_WPS_TESTING */ 1817} 1818 1819 1820static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 1821 void *sock_ctx) 1822{ 1823 void *interfaces = eloop_ctx; 1824 char buf[256]; 1825 int res; 1826 struct sockaddr_un from; 1827 socklen_t fromlen = sizeof(from); 1828 char reply[24]; 1829 int reply_len; 1830 1831 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1832 (struct sockaddr *) &from, &fromlen); 1833 if (res < 0) { 1834 perror("recvfrom(ctrl_iface)"); 1835 return; 1836 } 1837 buf[res] = '\0'; 1838 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 1839 1840 os_memcpy(reply, "OK\n", 3); 1841 reply_len = 3; 1842 1843 if (os_strcmp(buf, "PING") == 0) { 1844 os_memcpy(reply, "PONG\n", 5); 1845 reply_len = 5; 1846 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 1847 if (wpa_debug_reopen_file() < 0) 1848 reply_len = -1; 1849 } else if (os_strcmp(buf, "FLUSH") == 0) { 1850 hostapd_ctrl_iface_flush(interfaces); 1851 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 1852 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 1853 reply_len = -1; 1854 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 1855 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 1856 reply_len = -1; 1857#ifdef CONFIG_MODULE_TESTS 1858 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 1859 int hapd_module_tests(void); 1860 if (hapd_module_tests() < 0) 1861 reply_len = -1; 1862#endif /* CONFIG_MODULE_TESTS */ 1863 } else { 1864 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 1865 "ignored"); 1866 reply_len = -1; 1867 } 1868 1869 if (reply_len < 0) { 1870 os_memcpy(reply, "FAIL\n", 5); 1871 reply_len = 5; 1872 } 1873 1874 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 1875} 1876 1877 1878static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 1879{ 1880 char *buf; 1881 size_t len; 1882 1883 if (interface->global_iface_path == NULL) 1884 return NULL; 1885 1886 len = os_strlen(interface->global_iface_path) + 1887 os_strlen(interface->global_iface_name) + 2; 1888 buf = os_malloc(len); 1889 if (buf == NULL) 1890 return NULL; 1891 1892 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 1893 interface->global_iface_name); 1894 buf[len - 1] = '\0'; 1895 return buf; 1896} 1897 1898 1899int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 1900{ 1901 struct sockaddr_un addr; 1902 int s = -1; 1903 char *fname = NULL; 1904 1905 if (interface->global_iface_path == NULL) { 1906 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 1907 return 0; 1908 } 1909 1910 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 1911 if (errno == EEXIST) { 1912 wpa_printf(MSG_DEBUG, "Using existing control " 1913 "interface directory."); 1914 } else { 1915 perror("mkdir[ctrl_interface]"); 1916 goto fail; 1917 } 1918 } else if (interface->ctrl_iface_group && 1919 chown(interface->global_iface_path, -1, 1920 interface->ctrl_iface_group) < 0) { 1921 perror("chown[ctrl_interface]"); 1922 goto fail; 1923 } 1924 1925 if (os_strlen(interface->global_iface_path) + 1 + 1926 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 1927 goto fail; 1928 1929 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1930 if (s < 0) { 1931 perror("socket(PF_UNIX)"); 1932 goto fail; 1933 } 1934 1935 os_memset(&addr, 0, sizeof(addr)); 1936#ifdef __FreeBSD__ 1937 addr.sun_len = sizeof(addr); 1938#endif /* __FreeBSD__ */ 1939 addr.sun_family = AF_UNIX; 1940 fname = hostapd_global_ctrl_iface_path(interface); 1941 if (fname == NULL) 1942 goto fail; 1943 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1944 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1945 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1946 strerror(errno)); 1947 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1948 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1949 " allow connections - assuming it was left" 1950 "over from forced program termination"); 1951 if (unlink(fname) < 0) { 1952 perror("unlink[ctrl_iface]"); 1953 wpa_printf(MSG_ERROR, "Could not unlink " 1954 "existing ctrl_iface socket '%s'", 1955 fname); 1956 goto fail; 1957 } 1958 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1959 0) { 1960 perror("bind(PF_UNIX)"); 1961 goto fail; 1962 } 1963 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1964 "ctrl_iface socket '%s'", fname); 1965 } else { 1966 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1967 "be in use - cannot override it"); 1968 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1969 "not used anymore", fname); 1970 os_free(fname); 1971 fname = NULL; 1972 goto fail; 1973 } 1974 } 1975 1976 if (interface->ctrl_iface_group && 1977 chown(fname, -1, interface->ctrl_iface_group) < 0) { 1978 perror("chown[ctrl_interface]"); 1979 goto fail; 1980 } 1981 1982 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1983 perror("chmod[ctrl_interface/ifname]"); 1984 goto fail; 1985 } 1986 os_free(fname); 1987 1988 interface->global_ctrl_sock = s; 1989 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 1990 interface, NULL); 1991 1992 return 0; 1993 1994fail: 1995 if (s >= 0) 1996 close(s); 1997 if (fname) { 1998 unlink(fname); 1999 os_free(fname); 2000 } 2001 return -1; 2002} 2003 2004 2005void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 2006{ 2007 char *fname = NULL; 2008 2009 if (interfaces->global_ctrl_sock > -1) { 2010 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 2011 close(interfaces->global_ctrl_sock); 2012 interfaces->global_ctrl_sock = -1; 2013 fname = hostapd_global_ctrl_iface_path(interfaces); 2014 if (fname) { 2015 unlink(fname); 2016 os_free(fname); 2017 } 2018 2019 if (interfaces->global_iface_path && 2020 rmdir(interfaces->global_iface_path) < 0) { 2021 if (errno == ENOTEMPTY) { 2022 wpa_printf(MSG_DEBUG, "Control interface " 2023 "directory not empty - leaving it " 2024 "behind"); 2025 } else { 2026 wpa_printf(MSG_ERROR, 2027 "rmdir[ctrl_interface=%s]: %s", 2028 interfaces->global_iface_path, 2029 strerror(errno)); 2030 } 2031 } 2032 os_free(interfaces->global_iface_path); 2033 interfaces->global_iface_path = NULL; 2034 } 2035} 2036 2037 2038static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 2039 const char *buf, size_t len) 2040{ 2041 struct wpa_ctrl_dst *dst, *next; 2042 struct msghdr msg; 2043 int idx; 2044 struct iovec io[2]; 2045 char levelstr[10]; 2046 2047 dst = hapd->ctrl_dst; 2048 if (hapd->ctrl_sock < 0 || dst == NULL) 2049 return; 2050 2051 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 2052 io[0].iov_base = levelstr; 2053 io[0].iov_len = os_strlen(levelstr); 2054 io[1].iov_base = (char *) buf; 2055 io[1].iov_len = len; 2056 os_memset(&msg, 0, sizeof(msg)); 2057 msg.msg_iov = io; 2058 msg.msg_iovlen = 2; 2059 2060 idx = 0; 2061 while (dst) { 2062 next = dst->next; 2063 if (level >= dst->debug_level) { 2064 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 2065 (u8 *) dst->addr.sun_path, dst->addrlen - 2066 offsetof(struct sockaddr_un, sun_path)); 2067 msg.msg_name = &dst->addr; 2068 msg.msg_namelen = dst->addrlen; 2069 if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { 2070 int _errno = errno; 2071 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 2072 "%d - %s", 2073 idx, errno, strerror(errno)); 2074 dst->errors++; 2075 if (dst->errors > 10 || _errno == ENOENT) { 2076 hostapd_ctrl_iface_detach( 2077 hapd, &dst->addr, 2078 dst->addrlen); 2079 } 2080 } else 2081 dst->errors = 0; 2082 } 2083 idx++; 2084 dst = next; 2085 } 2086} 2087 2088#endif /* CONFIG_NATIVE_WINDOWS */ 2089