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