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