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