1 /* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2012, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #ifndef CONFIG_NATIVE_WINDOWS 12 13 #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 39 struct 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 48 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 49 const char *buf, size_t len); 50 51 52 static 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 73 static 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 103 static 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 131 static 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 159 static 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 180 static 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 209 static 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 255 static 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 282 static 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 312 static 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 334 static 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 358 static 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 397 static 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 412 static 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 465 static 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 492 static 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 509 static 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_WNM 563 564 static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 565 const char *cmd) 566 { 567 u8 addr[ETH_ALEN]; 568 u8 buf[1000], *pos; 569 struct ieee80211_mgmt *mgmt; 570 int disassoc_timer; 571 572 if (hwaddr_aton(cmd, addr)) 573 return -1; 574 if (cmd[17] != ' ') 575 return -1; 576 disassoc_timer = atoi(cmd + 17); 577 578 os_memset(buf, 0, sizeof(buf)); 579 mgmt = (struct ieee80211_mgmt *) buf; 580 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 581 WLAN_FC_STYPE_ACTION); 582 os_memcpy(mgmt->da, addr, ETH_ALEN); 583 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 584 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 585 mgmt->u.action.category = WLAN_ACTION_WNM; 586 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 587 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 588 mgmt->u.action.u.bss_tm_req.req_mode = 589 WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 590 mgmt->u.action.u.bss_tm_req.disassoc_timer = 591 host_to_le16(disassoc_timer); 592 mgmt->u.action.u.bss_tm_req.validity_interval = 0; 593 594 pos = mgmt->u.action.u.bss_tm_req.variable; 595 596 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { 597 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " 598 "Management Request frame"); 599 return -1; 600 } 601 602 return 0; 603 } 604 605 606 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 607 const char *cmd) 608 { 609 u8 addr[ETH_ALEN]; 610 const char *url, *timerstr; 611 u8 buf[1000], *pos; 612 struct ieee80211_mgmt *mgmt; 613 size_t url_len; 614 int disassoc_timer; 615 616 if (hwaddr_aton(cmd, addr)) 617 return -1; 618 619 timerstr = cmd + 17; 620 if (*timerstr != ' ') 621 return -1; 622 timerstr++; 623 disassoc_timer = atoi(timerstr); 624 if (disassoc_timer < 0 || disassoc_timer > 65535) 625 return -1; 626 627 url = os_strchr(timerstr, ' '); 628 if (url == NULL) 629 return -1; 630 url++; 631 url_len = os_strlen(url); 632 if (url_len > 255) 633 return -1; 634 635 os_memset(buf, 0, sizeof(buf)); 636 mgmt = (struct ieee80211_mgmt *) buf; 637 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 638 WLAN_FC_STYPE_ACTION); 639 os_memcpy(mgmt->da, addr, ETH_ALEN); 640 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 641 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 642 mgmt->u.action.category = WLAN_ACTION_WNM; 643 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 644 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 645 mgmt->u.action.u.bss_tm_req.req_mode = 646 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 647 mgmt->u.action.u.bss_tm_req.disassoc_timer = 648 host_to_le16(disassoc_timer); 649 mgmt->u.action.u.bss_tm_req.validity_interval = 0x01; 650 651 pos = mgmt->u.action.u.bss_tm_req.variable; 652 653 /* Session Information URL */ 654 *pos++ = url_len; 655 os_memcpy(pos, url, url_len); 656 pos += url_len; 657 658 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { 659 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " 660 "Management Request frame"); 661 return -1; 662 } 663 664 /* send disassociation frame after time-out */ 665 if (disassoc_timer) { 666 struct sta_info *sta; 667 int timeout, beacon_int; 668 669 /* 670 * Prevent STA from reconnecting using cached PMKSA to force 671 * full authentication with the authentication server (which may 672 * decide to reject the connection), 673 */ 674 wpa_auth_pmksa_remove(hapd->wpa_auth, addr); 675 676 sta = ap_get_sta(hapd, addr); 677 if (sta == NULL) { 678 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 679 "for ESS disassociation imminent message", 680 MAC2STR(addr)); 681 return -1; 682 } 683 684 beacon_int = hapd->iconf->beacon_int; 685 if (beacon_int < 1) 686 beacon_int = 100; /* best guess */ 687 /* Calculate timeout in ms based on beacon_int in TU */ 688 timeout = disassoc_timer * beacon_int * 128 / 125; 689 wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR 690 " set to %d ms", MAC2STR(addr), timeout); 691 692 sta->timeout_next = STA_DISASSOC_FROM_CLI; 693 eloop_cancel_timeout(ap_handle_timer, hapd, sta); 694 eloop_register_timeout(timeout / 1000, 695 timeout % 1000 * 1000, 696 ap_handle_timer, hapd, sta); 697 } 698 699 return 0; 700 } 701 702 #endif /* CONFIG_WNM */ 703 704 705 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 706 char *buf, size_t buflen) 707 { 708 int ret; 709 char *pos, *end; 710 711 pos = buf; 712 end = buf + buflen; 713 714 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 715 "ssid=%s\n", 716 MAC2STR(hapd->own_addr), 717 wpa_ssid_txt(hapd->conf->ssid.ssid, 718 hapd->conf->ssid.ssid_len)); 719 if (ret < 0 || ret >= end - pos) 720 return pos - buf; 721 pos += ret; 722 723 #ifdef CONFIG_WPS 724 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 725 hapd->conf->wps_state == 0 ? "disabled" : 726 (hapd->conf->wps_state == 1 ? "not configured" : 727 "configured")); 728 if (ret < 0 || ret >= end - pos) 729 return pos - buf; 730 pos += ret; 731 732 if (hapd->conf->wps_state && hapd->conf->wpa && 733 hapd->conf->ssid.wpa_passphrase) { 734 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 735 hapd->conf->ssid.wpa_passphrase); 736 if (ret < 0 || ret >= end - pos) 737 return pos - buf; 738 pos += ret; 739 } 740 741 if (hapd->conf->wps_state && hapd->conf->wpa && 742 hapd->conf->ssid.wpa_psk && 743 hapd->conf->ssid.wpa_psk->group) { 744 char hex[PMK_LEN * 2 + 1]; 745 wpa_snprintf_hex(hex, sizeof(hex), 746 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 747 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 748 if (ret < 0 || ret >= end - pos) 749 return pos - buf; 750 pos += ret; 751 } 752 #endif /* CONFIG_WPS */ 753 754 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 755 ret = os_snprintf(pos, end - pos, "key_mgmt="); 756 if (ret < 0 || ret >= end - pos) 757 return pos - buf; 758 pos += ret; 759 760 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 761 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 762 if (ret < 0 || ret >= end - pos) 763 return pos - buf; 764 pos += ret; 765 } 766 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 767 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 768 if (ret < 0 || ret >= end - pos) 769 return pos - buf; 770 pos += ret; 771 } 772 #ifdef CONFIG_IEEE80211R 773 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 774 ret = os_snprintf(pos, end - pos, "FT-PSK "); 775 if (ret < 0 || ret >= end - pos) 776 return pos - buf; 777 pos += ret; 778 } 779 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 780 ret = os_snprintf(pos, end - pos, "FT-EAP "); 781 if (ret < 0 || ret >= end - pos) 782 return pos - buf; 783 pos += ret; 784 } 785 #endif /* CONFIG_IEEE80211R */ 786 #ifdef CONFIG_IEEE80211W 787 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 788 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 789 if (ret < 0 || ret >= end - pos) 790 return pos - buf; 791 pos += ret; 792 } 793 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 794 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 795 if (ret < 0 || ret >= end - pos) 796 return pos - buf; 797 pos += ret; 798 } 799 #endif /* CONFIG_IEEE80211W */ 800 801 ret = os_snprintf(pos, end - pos, "\n"); 802 if (ret < 0 || ret >= end - pos) 803 return pos - buf; 804 pos += ret; 805 } 806 807 if (hapd->conf->wpa) { 808 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 809 wpa_cipher_txt(hapd->conf->wpa_group)); 810 if (ret < 0 || ret >= end - pos) 811 return pos - buf; 812 pos += ret; 813 } 814 815 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 816 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 817 if (ret < 0 || ret >= end - pos) 818 return pos - buf; 819 pos += ret; 820 821 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 822 " "); 823 if (ret < 0) 824 return pos - buf; 825 pos += ret; 826 827 ret = os_snprintf(pos, end - pos, "\n"); 828 if (ret < 0 || ret >= end - pos) 829 return pos - buf; 830 pos += ret; 831 } 832 833 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 834 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 835 if (ret < 0 || ret >= end - pos) 836 return pos - buf; 837 pos += ret; 838 839 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 840 " "); 841 if (ret < 0) 842 return pos - buf; 843 pos += ret; 844 845 ret = os_snprintf(pos, end - pos, "\n"); 846 if (ret < 0 || ret >= end - pos) 847 return pos - buf; 848 pos += ret; 849 } 850 851 return pos - buf; 852 } 853 854 855 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 856 { 857 char *value; 858 int ret = 0; 859 860 value = os_strchr(cmd, ' '); 861 if (value == NULL) 862 return -1; 863 *value++ = '\0'; 864 865 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 866 if (0) { 867 #ifdef CONFIG_WPS_TESTING 868 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 869 long int val; 870 val = strtol(value, NULL, 0); 871 if (val < 0 || val > 0xff) { 872 ret = -1; 873 wpa_printf(MSG_DEBUG, "WPS: Invalid " 874 "wps_version_number %ld", val); 875 } else { 876 wps_version_number = val; 877 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 878 "version %u.%u", 879 (wps_version_number & 0xf0) >> 4, 880 wps_version_number & 0x0f); 881 hostapd_wps_update_ie(hapd); 882 } 883 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 884 wps_testing_dummy_cred = atoi(value); 885 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 886 wps_testing_dummy_cred); 887 #endif /* CONFIG_WPS_TESTING */ 888 #ifdef CONFIG_INTERWORKING 889 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) { 890 int val = atoi(value); 891 if (val <= 0) 892 ret = -1; 893 else 894 hapd->gas_frag_limit = val; 895 #endif /* CONFIG_INTERWORKING */ 896 } else { 897 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 898 } 899 900 return ret; 901 } 902 903 904 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 905 char *buf, size_t buflen) 906 { 907 int res; 908 909 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 910 911 if (os_strcmp(cmd, "version") == 0) { 912 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 913 if (res < 0 || (unsigned int) res >= buflen) 914 return -1; 915 return res; 916 } 917 918 return -1; 919 } 920 921 922 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 923 { 924 if (hostapd_enable_iface(iface) < 0) { 925 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 926 return -1; 927 } 928 return 0; 929 } 930 931 932 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 933 { 934 if (hostapd_reload_iface(iface) < 0) { 935 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 936 return -1; 937 } 938 return 0; 939 } 940 941 942 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 943 { 944 if (hostapd_disable_iface(iface) < 0) { 945 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 946 return -1; 947 } 948 return 0; 949 } 950 951 952 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 953 void *sock_ctx) 954 { 955 struct hostapd_data *hapd = eloop_ctx; 956 char buf[256]; 957 int res; 958 struct sockaddr_un from; 959 socklen_t fromlen = sizeof(from); 960 char *reply; 961 const int reply_size = 4096; 962 int reply_len; 963 int level = MSG_DEBUG; 964 965 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 966 (struct sockaddr *) &from, &fromlen); 967 if (res < 0) { 968 perror("recvfrom(ctrl_iface)"); 969 return; 970 } 971 buf[res] = '\0'; 972 if (os_strcmp(buf, "PING") == 0) 973 level = MSG_EXCESSIVE; 974 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 975 976 reply = os_malloc(reply_size); 977 if (reply == NULL) { 978 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 979 fromlen); 980 return; 981 } 982 983 os_memcpy(reply, "OK\n", 3); 984 reply_len = 3; 985 986 if (os_strcmp(buf, "PING") == 0) { 987 os_memcpy(reply, "PONG\n", 5); 988 reply_len = 5; 989 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 990 if (wpa_debug_reopen_file() < 0) 991 reply_len = -1; 992 } else if (os_strcmp(buf, "MIB") == 0) { 993 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 994 if (reply_len >= 0) { 995 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 996 reply_size - reply_len); 997 if (res < 0) 998 reply_len = -1; 999 else 1000 reply_len += res; 1001 } 1002 if (reply_len >= 0) { 1003 res = ieee802_1x_get_mib(hapd, reply + reply_len, 1004 reply_size - reply_len); 1005 if (res < 0) 1006 reply_len = -1; 1007 else 1008 reply_len += res; 1009 } 1010 #ifndef CONFIG_NO_RADIUS 1011 if (reply_len >= 0) { 1012 res = radius_client_get_mib(hapd->radius, 1013 reply + reply_len, 1014 reply_size - reply_len); 1015 if (res < 0) 1016 reply_len = -1; 1017 else 1018 reply_len += res; 1019 } 1020 #endif /* CONFIG_NO_RADIUS */ 1021 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 1022 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 1023 reply_size); 1024 } else if (os_strncmp(buf, "STA ", 4) == 0) { 1025 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 1026 reply_size); 1027 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 1028 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 1029 reply_size); 1030 } else if (os_strcmp(buf, "ATTACH") == 0) { 1031 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 1032 reply_len = -1; 1033 } else if (os_strcmp(buf, "DETACH") == 0) { 1034 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 1035 reply_len = -1; 1036 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 1037 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 1038 buf + 6)) 1039 reply_len = -1; 1040 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 1041 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 1042 reply_len = -1; 1043 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 1044 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 1045 reply_len = -1; 1046 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 1047 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 1048 reply_len = -1; 1049 #ifdef CONFIG_IEEE80211W 1050 #ifdef NEED_AP_MLME 1051 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 1052 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 1053 reply_len = -1; 1054 #endif /* NEED_AP_MLME */ 1055 #endif /* CONFIG_IEEE80211W */ 1056 #ifdef CONFIG_WPS 1057 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1058 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 1059 reply_len = -1; 1060 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 1061 reply_len = hostapd_ctrl_iface_wps_check_pin( 1062 hapd, buf + 14, reply, reply_size); 1063 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1064 if (hostapd_wps_button_pushed(hapd, NULL)) 1065 reply_len = -1; 1066 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 1067 if (hostapd_wps_cancel(hapd)) 1068 reply_len = -1; 1069 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 1070 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 1071 reply, reply_size); 1072 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 1073 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 1074 reply_len = -1; 1075 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 1076 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 1077 reply_size); 1078 #ifdef CONFIG_WPS_NFC 1079 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 1080 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 1081 reply_len = -1; 1082 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 1083 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 1084 hapd, buf + 21, reply, reply_size); 1085 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 1086 reply_len = hostapd_ctrl_iface_wps_nfc_token( 1087 hapd, buf + 14, reply, reply_size); 1088 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 1089 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 1090 hapd, buf + 21, reply, reply_size); 1091 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 1092 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 1093 reply_len = -1; 1094 #endif /* CONFIG_WPS_NFC */ 1095 #endif /* CONFIG_WPS */ 1096 #ifdef CONFIG_WNM 1097 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 1098 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 1099 reply_len = -1; 1100 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 1101 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 1102 reply_len = -1; 1103 #endif /* CONFIG_WNM */ 1104 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 1105 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 1106 reply_size); 1107 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1108 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 1109 reply_len = -1; 1110 } else if (os_strncmp(buf, "GET ", 4) == 0) { 1111 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 1112 reply_size); 1113 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 1114 if (hostapd_ctrl_iface_enable(hapd->iface)) 1115 reply_len = -1; 1116 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 1117 if (hostapd_ctrl_iface_reload(hapd->iface)) 1118 reply_len = -1; 1119 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 1120 if (hostapd_ctrl_iface_disable(hapd->iface)) 1121 reply_len = -1; 1122 } else { 1123 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 1124 reply_len = 16; 1125 } 1126 1127 if (reply_len < 0) { 1128 os_memcpy(reply, "FAIL\n", 5); 1129 reply_len = 5; 1130 } 1131 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 1132 os_free(reply); 1133 } 1134 1135 1136 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 1137 { 1138 char *buf; 1139 size_t len; 1140 1141 if (hapd->conf->ctrl_interface == NULL) 1142 return NULL; 1143 1144 len = os_strlen(hapd->conf->ctrl_interface) + 1145 os_strlen(hapd->conf->iface) + 2; 1146 buf = os_malloc(len); 1147 if (buf == NULL) 1148 return NULL; 1149 1150 os_snprintf(buf, len, "%s/%s", 1151 hapd->conf->ctrl_interface, hapd->conf->iface); 1152 buf[len - 1] = '\0'; 1153 return buf; 1154 } 1155 1156 1157 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global, 1158 const char *txt, size_t len) 1159 { 1160 struct hostapd_data *hapd = ctx; 1161 if (hapd == NULL) 1162 return; 1163 hostapd_ctrl_iface_send(hapd, level, txt, len); 1164 } 1165 1166 1167 int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 1168 { 1169 struct sockaddr_un addr; 1170 int s = -1; 1171 char *fname = NULL; 1172 1173 if (hapd->ctrl_sock > -1) { 1174 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 1175 return 0; 1176 } 1177 1178 if (hapd->conf->ctrl_interface == NULL) 1179 return 0; 1180 1181 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 1182 if (errno == EEXIST) { 1183 wpa_printf(MSG_DEBUG, "Using existing control " 1184 "interface directory."); 1185 } else { 1186 perror("mkdir[ctrl_interface]"); 1187 goto fail; 1188 } 1189 } 1190 1191 if (hapd->conf->ctrl_interface_gid_set && 1192 chown(hapd->conf->ctrl_interface, -1, 1193 hapd->conf->ctrl_interface_gid) < 0) { 1194 perror("chown[ctrl_interface]"); 1195 return -1; 1196 } 1197 1198 if (!hapd->conf->ctrl_interface_gid_set && 1199 hapd->iface->interfaces->ctrl_iface_group && 1200 chown(hapd->conf->ctrl_interface, -1, 1201 hapd->iface->interfaces->ctrl_iface_group) < 0) { 1202 perror("chown[ctrl_interface]"); 1203 return -1; 1204 } 1205 1206 #ifdef ANDROID 1207 /* 1208 * Android is using umask 0077 which would leave the control interface 1209 * directory without group access. This breaks things since Wi-Fi 1210 * framework assumes that this directory can be accessed by other 1211 * applications in the wifi group. Fix this by adding group access even 1212 * if umask value would prevent this. 1213 */ 1214 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 1215 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 1216 strerror(errno)); 1217 /* Try to continue anyway */ 1218 } 1219 #endif /* ANDROID */ 1220 1221 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 1222 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 1223 goto fail; 1224 1225 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1226 if (s < 0) { 1227 perror("socket(PF_UNIX)"); 1228 goto fail; 1229 } 1230 1231 os_memset(&addr, 0, sizeof(addr)); 1232 #ifdef __FreeBSD__ 1233 addr.sun_len = sizeof(addr); 1234 #endif /* __FreeBSD__ */ 1235 addr.sun_family = AF_UNIX; 1236 fname = hostapd_ctrl_iface_path(hapd); 1237 if (fname == NULL) 1238 goto fail; 1239 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1240 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1241 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1242 strerror(errno)); 1243 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1244 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1245 " allow connections - assuming it was left" 1246 "over from forced program termination"); 1247 if (unlink(fname) < 0) { 1248 perror("unlink[ctrl_iface]"); 1249 wpa_printf(MSG_ERROR, "Could not unlink " 1250 "existing ctrl_iface socket '%s'", 1251 fname); 1252 goto fail; 1253 } 1254 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1255 0) { 1256 perror("hostapd-ctrl-iface: bind(PF_UNIX)"); 1257 goto fail; 1258 } 1259 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1260 "ctrl_iface socket '%s'", fname); 1261 } else { 1262 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1263 "be in use - cannot override it"); 1264 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1265 "not used anymore", fname); 1266 os_free(fname); 1267 fname = NULL; 1268 goto fail; 1269 } 1270 } 1271 1272 if (hapd->conf->ctrl_interface_gid_set && 1273 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 1274 perror("chown[ctrl_interface/ifname]"); 1275 goto fail; 1276 } 1277 1278 if (!hapd->conf->ctrl_interface_gid_set && 1279 hapd->iface->interfaces->ctrl_iface_group && 1280 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 1281 perror("chown[ctrl_interface/ifname]"); 1282 goto fail; 1283 } 1284 1285 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1286 perror("chmod[ctrl_interface/ifname]"); 1287 goto fail; 1288 } 1289 os_free(fname); 1290 1291 hapd->ctrl_sock = s; 1292 eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 1293 NULL); 1294 hapd->msg_ctx = hapd; 1295 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 1296 1297 return 0; 1298 1299 fail: 1300 if (s >= 0) 1301 close(s); 1302 if (fname) { 1303 unlink(fname); 1304 os_free(fname); 1305 } 1306 return -1; 1307 } 1308 1309 1310 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 1311 { 1312 struct wpa_ctrl_dst *dst, *prev; 1313 1314 if (hapd->ctrl_sock > -1) { 1315 char *fname; 1316 eloop_unregister_read_sock(hapd->ctrl_sock); 1317 close(hapd->ctrl_sock); 1318 hapd->ctrl_sock = -1; 1319 fname = hostapd_ctrl_iface_path(hapd); 1320 if (fname) 1321 unlink(fname); 1322 os_free(fname); 1323 1324 if (hapd->conf->ctrl_interface && 1325 rmdir(hapd->conf->ctrl_interface) < 0) { 1326 if (errno == ENOTEMPTY) { 1327 wpa_printf(MSG_DEBUG, "Control interface " 1328 "directory not empty - leaving it " 1329 "behind"); 1330 } else { 1331 wpa_printf(MSG_ERROR, 1332 "rmdir[ctrl_interface=%s]: %s", 1333 hapd->conf->ctrl_interface, 1334 strerror(errno)); 1335 } 1336 } 1337 } 1338 1339 dst = hapd->ctrl_dst; 1340 while (dst) { 1341 prev = dst; 1342 dst = dst->next; 1343 os_free(prev); 1344 } 1345 } 1346 1347 1348 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 1349 char *buf) 1350 { 1351 if (hostapd_add_iface(interfaces, buf) < 0) { 1352 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 1353 return -1; 1354 } 1355 return 0; 1356 } 1357 1358 1359 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 1360 char *buf) 1361 { 1362 if (hostapd_remove_iface(interfaces, buf) < 0) { 1363 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 1364 return -1; 1365 } 1366 return 0; 1367 } 1368 1369 1370 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 1371 void *sock_ctx) 1372 { 1373 void *interfaces = eloop_ctx; 1374 char buf[256]; 1375 int res; 1376 struct sockaddr_un from; 1377 socklen_t fromlen = sizeof(from); 1378 char reply[24]; 1379 int reply_len; 1380 1381 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1382 (struct sockaddr *) &from, &fromlen); 1383 if (res < 0) { 1384 perror("recvfrom(ctrl_iface)"); 1385 return; 1386 } 1387 buf[res] = '\0'; 1388 1389 os_memcpy(reply, "OK\n", 3); 1390 reply_len = 3; 1391 1392 if (os_strcmp(buf, "PING") == 0) { 1393 os_memcpy(reply, "PONG\n", 5); 1394 reply_len = 5; 1395 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 1396 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 1397 reply_len = -1; 1398 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 1399 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 1400 reply_len = -1; 1401 } else { 1402 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 1403 "ignored"); 1404 reply_len = -1; 1405 } 1406 1407 if (reply_len < 0) { 1408 os_memcpy(reply, "FAIL\n", 5); 1409 reply_len = 5; 1410 } 1411 1412 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 1413 } 1414 1415 1416 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 1417 { 1418 char *buf; 1419 size_t len; 1420 1421 if (interface->global_iface_path == NULL) 1422 return NULL; 1423 1424 len = os_strlen(interface->global_iface_path) + 1425 os_strlen(interface->global_iface_name) + 2; 1426 buf = os_malloc(len); 1427 if (buf == NULL) 1428 return NULL; 1429 1430 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 1431 interface->global_iface_name); 1432 buf[len - 1] = '\0'; 1433 return buf; 1434 } 1435 1436 1437 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 1438 { 1439 struct sockaddr_un addr; 1440 int s = -1; 1441 char *fname = NULL; 1442 1443 if (interface->global_iface_path == NULL) { 1444 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 1445 return 0; 1446 } 1447 1448 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 1449 if (errno == EEXIST) { 1450 wpa_printf(MSG_DEBUG, "Using existing control " 1451 "interface directory."); 1452 } else { 1453 perror("mkdir[ctrl_interface]"); 1454 goto fail; 1455 } 1456 } else if (interface->ctrl_iface_group && 1457 chown(interface->global_iface_path, -1, 1458 interface->ctrl_iface_group) < 0) { 1459 perror("chown[ctrl_interface]"); 1460 goto fail; 1461 } 1462 1463 if (os_strlen(interface->global_iface_path) + 1 + 1464 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 1465 goto fail; 1466 1467 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1468 if (s < 0) { 1469 perror("socket(PF_UNIX)"); 1470 goto fail; 1471 } 1472 1473 os_memset(&addr, 0, sizeof(addr)); 1474 #ifdef __FreeBSD__ 1475 addr.sun_len = sizeof(addr); 1476 #endif /* __FreeBSD__ */ 1477 addr.sun_family = AF_UNIX; 1478 fname = hostapd_global_ctrl_iface_path(interface); 1479 if (fname == NULL) 1480 goto fail; 1481 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1482 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1483 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1484 strerror(errno)); 1485 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1486 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1487 " allow connections - assuming it was left" 1488 "over from forced program termination"); 1489 if (unlink(fname) < 0) { 1490 perror("unlink[ctrl_iface]"); 1491 wpa_printf(MSG_ERROR, "Could not unlink " 1492 "existing ctrl_iface socket '%s'", 1493 fname); 1494 goto fail; 1495 } 1496 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1497 0) { 1498 perror("bind(PF_UNIX)"); 1499 goto fail; 1500 } 1501 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1502 "ctrl_iface socket '%s'", fname); 1503 } else { 1504 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1505 "be in use - cannot override it"); 1506 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1507 "not used anymore", fname); 1508 os_free(fname); 1509 fname = NULL; 1510 goto fail; 1511 } 1512 } 1513 1514 if (interface->ctrl_iface_group && 1515 chown(fname, -1, interface->ctrl_iface_group) < 0) { 1516 perror("chown[ctrl_interface]"); 1517 goto fail; 1518 } 1519 1520 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1521 perror("chmod[ctrl_interface/ifname]"); 1522 goto fail; 1523 } 1524 os_free(fname); 1525 1526 interface->global_ctrl_sock = s; 1527 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 1528 interface, NULL); 1529 1530 return 0; 1531 1532 fail: 1533 if (s >= 0) 1534 close(s); 1535 if (fname) { 1536 unlink(fname); 1537 os_free(fname); 1538 } 1539 return -1; 1540 } 1541 1542 1543 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 1544 { 1545 char *fname = NULL; 1546 1547 if (interfaces->global_ctrl_sock > -1) { 1548 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 1549 close(interfaces->global_ctrl_sock); 1550 interfaces->global_ctrl_sock = -1; 1551 fname = hostapd_global_ctrl_iface_path(interfaces); 1552 if (fname) { 1553 unlink(fname); 1554 os_free(fname); 1555 } 1556 1557 if (interfaces->global_iface_path && 1558 rmdir(interfaces->global_iface_path) < 0) { 1559 if (errno == ENOTEMPTY) { 1560 wpa_printf(MSG_DEBUG, "Control interface " 1561 "directory not empty - leaving it " 1562 "behind"); 1563 } else { 1564 wpa_printf(MSG_ERROR, 1565 "rmdir[ctrl_interface=%s]: %s", 1566 interfaces->global_iface_path, 1567 strerror(errno)); 1568 } 1569 } 1570 os_free(interfaces->global_iface_path); 1571 interfaces->global_iface_path = NULL; 1572 } 1573 } 1574 1575 1576 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 1577 const char *buf, size_t len) 1578 { 1579 struct wpa_ctrl_dst *dst, *next; 1580 struct msghdr msg; 1581 int idx; 1582 struct iovec io[2]; 1583 char levelstr[10]; 1584 1585 dst = hapd->ctrl_dst; 1586 if (hapd->ctrl_sock < 0 || dst == NULL) 1587 return; 1588 1589 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 1590 io[0].iov_base = levelstr; 1591 io[0].iov_len = os_strlen(levelstr); 1592 io[1].iov_base = (char *) buf; 1593 io[1].iov_len = len; 1594 os_memset(&msg, 0, sizeof(msg)); 1595 msg.msg_iov = io; 1596 msg.msg_iovlen = 2; 1597 1598 idx = 0; 1599 while (dst) { 1600 next = dst->next; 1601 if (level >= dst->debug_level) { 1602 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 1603 (u8 *) dst->addr.sun_path, dst->addrlen - 1604 offsetof(struct sockaddr_un, sun_path)); 1605 msg.msg_name = &dst->addr; 1606 msg.msg_namelen = dst->addrlen; 1607 if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { 1608 int _errno = errno; 1609 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 1610 "%d - %s", 1611 idx, errno, strerror(errno)); 1612 dst->errors++; 1613 if (dst->errors > 10 || _errno == ENOENT) { 1614 hostapd_ctrl_iface_detach( 1615 hapd, &dst->addr, 1616 dst->addrlen); 1617 } 1618 } else 1619 dst->errors = 0; 1620 } 1621 idx++; 1622 dst = next; 1623 } 1624 } 1625 1626 #endif /* CONFIG_NATIVE_WINDOWS */ 1627