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_OOB 254 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) 255 { 256 char *path, *method, *name; 257 258 path = os_strchr(txt, ' '); 259 if (path == NULL) 260 return -1; 261 *path++ = '\0'; 262 263 method = os_strchr(path, ' '); 264 if (method == NULL) 265 return -1; 266 *method++ = '\0'; 267 268 name = os_strchr(method, ' '); 269 if (name != NULL) 270 *name++ = '\0'; 271 272 return hostapd_wps_start_oob(hapd, txt, path, method, name); 273 } 274 #endif /* CONFIG_WPS_OOB */ 275 276 277 #ifdef CONFIG_WPS_NFC 278 static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 279 char *pos) 280 { 281 size_t len; 282 struct wpabuf *buf; 283 int ret; 284 285 len = os_strlen(pos); 286 if (len & 0x01) 287 return -1; 288 len /= 2; 289 290 buf = wpabuf_alloc(len); 291 if (buf == NULL) 292 return -1; 293 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 294 wpabuf_free(buf); 295 return -1; 296 } 297 298 ret = hostapd_wps_nfc_tag_read(hapd, buf); 299 wpabuf_free(buf); 300 301 return ret; 302 } 303 304 305 static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 306 char *cmd, char *reply, 307 size_t max_len) 308 { 309 int ndef; 310 struct wpabuf *buf; 311 int res; 312 313 if (os_strcmp(cmd, "WPS") == 0) 314 ndef = 0; 315 else if (os_strcmp(cmd, "NDEF") == 0) 316 ndef = 1; 317 else 318 return -1; 319 320 buf = hostapd_wps_nfc_config_token(hapd, ndef); 321 if (buf == NULL) 322 return -1; 323 324 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 325 wpabuf_len(buf)); 326 reply[res++] = '\n'; 327 reply[res] = '\0'; 328 329 wpabuf_free(buf); 330 331 return res; 332 } 333 334 335 static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 336 char *reply, size_t max_len, 337 int ndef) 338 { 339 struct wpabuf *buf; 340 int res; 341 342 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 343 if (buf == NULL) 344 return -1; 345 346 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 347 wpabuf_len(buf)); 348 reply[res++] = '\n'; 349 reply[res] = '\0'; 350 351 wpabuf_free(buf); 352 353 return res; 354 } 355 356 357 static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 358 char *cmd, char *reply, 359 size_t max_len) 360 { 361 if (os_strcmp(cmd, "WPS") == 0) 362 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 363 max_len, 0); 364 365 if (os_strcmp(cmd, "NDEF") == 0) 366 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 367 max_len, 1); 368 369 if (os_strcmp(cmd, "enable") == 0) 370 return hostapd_wps_nfc_token_enable(hapd); 371 372 if (os_strcmp(cmd, "disable") == 0) { 373 hostapd_wps_nfc_token_disable(hapd); 374 return 0; 375 } 376 377 return -1; 378 } 379 #endif /* CONFIG_WPS_NFC */ 380 381 382 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 383 char *buf, size_t buflen) 384 { 385 int timeout = 300; 386 char *pos; 387 const char *pin_txt; 388 389 pos = os_strchr(txt, ' '); 390 if (pos) 391 *pos++ = '\0'; 392 393 if (os_strcmp(txt, "disable") == 0) { 394 hostapd_wps_ap_pin_disable(hapd); 395 return os_snprintf(buf, buflen, "OK\n"); 396 } 397 398 if (os_strcmp(txt, "random") == 0) { 399 if (pos) 400 timeout = atoi(pos); 401 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 402 if (pin_txt == NULL) 403 return -1; 404 return os_snprintf(buf, buflen, "%s", pin_txt); 405 } 406 407 if (os_strcmp(txt, "get") == 0) { 408 pin_txt = hostapd_wps_ap_pin_get(hapd); 409 if (pin_txt == NULL) 410 return -1; 411 return os_snprintf(buf, buflen, "%s", pin_txt); 412 } 413 414 if (os_strcmp(txt, "set") == 0) { 415 char *pin; 416 if (pos == NULL) 417 return -1; 418 pin = pos; 419 pos = os_strchr(pos, ' '); 420 if (pos) { 421 *pos++ = '\0'; 422 timeout = atoi(pos); 423 } 424 if (os_strlen(pin) > buflen) 425 return -1; 426 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 427 return -1; 428 return os_snprintf(buf, buflen, "%s", pin); 429 } 430 431 return -1; 432 } 433 434 435 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 436 { 437 char *pos; 438 char *ssid, *auth, *encr = NULL, *key = NULL; 439 440 ssid = txt; 441 pos = os_strchr(txt, ' '); 442 if (!pos) 443 return -1; 444 *pos++ = '\0'; 445 446 auth = pos; 447 pos = os_strchr(pos, ' '); 448 if (pos) { 449 *pos++ = '\0'; 450 encr = pos; 451 pos = os_strchr(pos, ' '); 452 if (pos) { 453 *pos++ = '\0'; 454 key = pos; 455 } 456 } 457 458 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 459 } 460 #endif /* CONFIG_WPS */ 461 462 463 static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 464 const char *cmd) 465 { 466 u8 addr[ETH_ALEN]; 467 const char *url; 468 u8 buf[1000], *pos; 469 struct ieee80211_mgmt *mgmt; 470 size_t url_len; 471 472 if (hwaddr_aton(cmd, addr)) 473 return -1; 474 url = cmd + 17; 475 if (*url != ' ') 476 return -1; 477 url++; 478 url_len = os_strlen(url); 479 if (url_len > 255) 480 return -1; 481 482 os_memset(buf, 0, sizeof(buf)); 483 mgmt = (struct ieee80211_mgmt *) buf; 484 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 485 WLAN_FC_STYPE_ACTION); 486 os_memcpy(mgmt->da, addr, ETH_ALEN); 487 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 488 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 489 mgmt->u.action.category = WLAN_ACTION_WNM; 490 mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; 491 mgmt->u.action.u.bss_tm_req.dialog_token = 1; 492 mgmt->u.action.u.bss_tm_req.req_mode = 493 WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 494 mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0); 495 mgmt->u.action.u.bss_tm_req.validity_interval = 0; 496 497 pos = mgmt->u.action.u.bss_tm_req.variable; 498 499 /* Session Information URL */ 500 *pos++ = url_len; 501 os_memcpy(pos, url, url_len); 502 pos += url_len; 503 504 if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { 505 wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " 506 "Management Request frame"); 507 return -1; 508 } 509 510 return 0; 511 } 512 513 514 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 515 char *buf, size_t buflen) 516 { 517 int ret; 518 char *pos, *end; 519 520 pos = buf; 521 end = buf + buflen; 522 523 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 524 "ssid=%s\n", 525 MAC2STR(hapd->own_addr), 526 wpa_ssid_txt(hapd->conf->ssid.ssid, 527 hapd->conf->ssid.ssid_len)); 528 if (ret < 0 || ret >= end - pos) 529 return pos - buf; 530 pos += ret; 531 532 #ifdef CONFIG_WPS 533 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 534 hapd->conf->wps_state == 0 ? "disabled" : 535 (hapd->conf->wps_state == 1 ? "not configured" : 536 "configured")); 537 if (ret < 0 || ret >= end - pos) 538 return pos - buf; 539 pos += ret; 540 541 if (hapd->conf->wps_state && hapd->conf->wpa && 542 hapd->conf->ssid.wpa_passphrase) { 543 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 544 hapd->conf->ssid.wpa_passphrase); 545 if (ret < 0 || ret >= end - pos) 546 return pos - buf; 547 pos += ret; 548 } 549 550 if (hapd->conf->wps_state && hapd->conf->wpa && 551 hapd->conf->ssid.wpa_psk && 552 hapd->conf->ssid.wpa_psk->group) { 553 char hex[PMK_LEN * 2 + 1]; 554 wpa_snprintf_hex(hex, sizeof(hex), 555 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 556 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 557 if (ret < 0 || ret >= end - pos) 558 return pos - buf; 559 pos += ret; 560 } 561 #endif /* CONFIG_WPS */ 562 563 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 564 ret = os_snprintf(pos, end - pos, "key_mgmt="); 565 if (ret < 0 || ret >= end - pos) 566 return pos - buf; 567 pos += ret; 568 569 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 570 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 571 if (ret < 0 || ret >= end - pos) 572 return pos - buf; 573 pos += ret; 574 } 575 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 576 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 577 if (ret < 0 || ret >= end - pos) 578 return pos - buf; 579 pos += ret; 580 } 581 #ifdef CONFIG_IEEE80211R 582 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 583 ret = os_snprintf(pos, end - pos, "FT-PSK "); 584 if (ret < 0 || ret >= end - pos) 585 return pos - buf; 586 pos += ret; 587 } 588 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 589 ret = os_snprintf(pos, end - pos, "FT-EAP "); 590 if (ret < 0 || ret >= end - pos) 591 return pos - buf; 592 pos += ret; 593 } 594 #endif /* CONFIG_IEEE80211R */ 595 #ifdef CONFIG_IEEE80211W 596 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 597 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 598 if (ret < 0 || ret >= end - pos) 599 return pos - buf; 600 pos += ret; 601 } 602 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 603 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 604 if (ret < 0 || ret >= end - pos) 605 return pos - buf; 606 pos += ret; 607 } 608 #endif /* CONFIG_IEEE80211W */ 609 610 ret = os_snprintf(pos, end - pos, "\n"); 611 if (ret < 0 || ret >= end - pos) 612 return pos - buf; 613 pos += ret; 614 } 615 616 if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) { 617 ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n"); 618 if (ret < 0 || ret >= end - pos) 619 return pos - buf; 620 pos += ret; 621 } else if (hapd->conf->wpa && 622 hapd->conf->wpa_group == WPA_CIPHER_GCMP) { 623 ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n"); 624 if (ret < 0 || ret >= end - pos) 625 return pos - buf; 626 pos += ret; 627 } else if (hapd->conf->wpa && 628 hapd->conf->wpa_group == WPA_CIPHER_TKIP) { 629 ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n"); 630 if (ret < 0 || ret >= end - pos) 631 return pos - buf; 632 pos += ret; 633 } 634 635 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 636 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 637 if (ret < 0 || ret >= end - pos) 638 return pos - buf; 639 pos += ret; 640 641 if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) { 642 ret = os_snprintf(pos, end - pos, "CCMP "); 643 if (ret < 0 || ret >= end - pos) 644 return pos - buf; 645 pos += ret; 646 } 647 if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) { 648 ret = os_snprintf(pos, end - pos, "GCMP "); 649 if (ret < 0 || ret >= end - pos) 650 return pos - buf; 651 pos += ret; 652 } 653 if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) { 654 ret = os_snprintf(pos, end - pos, "TKIP "); 655 if (ret < 0 || ret >= end - pos) 656 return pos - buf; 657 pos += ret; 658 } 659 660 ret = os_snprintf(pos, end - pos, "\n"); 661 if (ret < 0 || ret >= end - pos) 662 return pos - buf; 663 pos += ret; 664 } 665 666 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 667 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 668 if (ret < 0 || ret >= end - pos) 669 return pos - buf; 670 pos += ret; 671 672 if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) { 673 ret = os_snprintf(pos, end - pos, "CCMP "); 674 if (ret < 0 || ret >= end - pos) 675 return pos - buf; 676 pos += ret; 677 } 678 if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) { 679 ret = os_snprintf(pos, end - pos, "GCMP "); 680 if (ret < 0 || ret >= end - pos) 681 return pos - buf; 682 pos += ret; 683 } 684 if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) { 685 ret = os_snprintf(pos, end - pos, "TKIP "); 686 if (ret < 0 || ret >= end - pos) 687 return pos - buf; 688 pos += ret; 689 } 690 691 ret = os_snprintf(pos, end - pos, "\n"); 692 if (ret < 0 || ret >= end - pos) 693 return pos - buf; 694 pos += ret; 695 } 696 697 return pos - buf; 698 } 699 700 701 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 702 { 703 char *value; 704 int ret = 0; 705 706 value = os_strchr(cmd, ' '); 707 if (value == NULL) 708 return -1; 709 *value++ = '\0'; 710 711 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 712 if (0) { 713 #ifdef CONFIG_WPS_TESTING 714 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 715 long int val; 716 val = strtol(value, NULL, 0); 717 if (val < 0 || val > 0xff) { 718 ret = -1; 719 wpa_printf(MSG_DEBUG, "WPS: Invalid " 720 "wps_version_number %ld", val); 721 } else { 722 wps_version_number = val; 723 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 724 "version %u.%u", 725 (wps_version_number & 0xf0) >> 4, 726 wps_version_number & 0x0f); 727 hostapd_wps_update_ie(hapd); 728 } 729 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 730 wps_testing_dummy_cred = atoi(value); 731 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 732 wps_testing_dummy_cred); 733 #endif /* CONFIG_WPS_TESTING */ 734 #ifdef CONFIG_INTERWORKING 735 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) { 736 int val = atoi(value); 737 if (val <= 0) 738 ret = -1; 739 else 740 hapd->gas_frag_limit = val; 741 #endif /* CONFIG_INTERWORKING */ 742 } else { 743 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 744 } 745 746 return ret; 747 } 748 749 750 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 751 char *buf, size_t buflen) 752 { 753 int res; 754 755 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 756 757 if (os_strcmp(cmd, "version") == 0) { 758 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 759 if (res < 0 || (unsigned int) res >= buflen) 760 return -1; 761 return res; 762 } 763 764 return -1; 765 } 766 767 768 static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 769 { 770 if (hostapd_enable_iface(iface) < 0) { 771 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 772 return -1; 773 } 774 return 0; 775 } 776 777 778 static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 779 { 780 if (hostapd_reload_iface(iface) < 0) { 781 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 782 return -1; 783 } 784 return 0; 785 } 786 787 788 static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 789 { 790 if (hostapd_disable_iface(iface) < 0) { 791 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 792 return -1; 793 } 794 return 0; 795 } 796 797 798 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 799 void *sock_ctx) 800 { 801 struct hostapd_data *hapd = eloop_ctx; 802 char buf[256]; 803 int res; 804 struct sockaddr_un from; 805 socklen_t fromlen = sizeof(from); 806 char *reply; 807 const int reply_size = 4096; 808 int reply_len; 809 int level = MSG_DEBUG; 810 811 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 812 (struct sockaddr *) &from, &fromlen); 813 if (res < 0) { 814 perror("recvfrom(ctrl_iface)"); 815 return; 816 } 817 buf[res] = '\0'; 818 if (os_strcmp(buf, "PING") == 0) 819 level = MSG_EXCESSIVE; 820 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 821 822 reply = os_malloc(reply_size); 823 if (reply == NULL) { 824 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 825 fromlen); 826 return; 827 } 828 829 os_memcpy(reply, "OK\n", 3); 830 reply_len = 3; 831 832 if (os_strcmp(buf, "PING") == 0) { 833 os_memcpy(reply, "PONG\n", 5); 834 reply_len = 5; 835 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 836 if (wpa_debug_reopen_file() < 0) 837 reply_len = -1; 838 } else if (os_strcmp(buf, "MIB") == 0) { 839 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 840 if (reply_len >= 0) { 841 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 842 reply_size - reply_len); 843 if (res < 0) 844 reply_len = -1; 845 else 846 reply_len += res; 847 } 848 if (reply_len >= 0) { 849 res = ieee802_1x_get_mib(hapd, reply + reply_len, 850 reply_size - reply_len); 851 if (res < 0) 852 reply_len = -1; 853 else 854 reply_len += res; 855 } 856 #ifndef CONFIG_NO_RADIUS 857 if (reply_len >= 0) { 858 res = radius_client_get_mib(hapd->radius, 859 reply + reply_len, 860 reply_size - reply_len); 861 if (res < 0) 862 reply_len = -1; 863 else 864 reply_len += res; 865 } 866 #endif /* CONFIG_NO_RADIUS */ 867 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 868 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 869 reply_size); 870 } else if (os_strncmp(buf, "STA ", 4) == 0) { 871 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 872 reply_size); 873 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 874 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 875 reply_size); 876 } else if (os_strcmp(buf, "ATTACH") == 0) { 877 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 878 reply_len = -1; 879 } else if (os_strcmp(buf, "DETACH") == 0) { 880 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 881 reply_len = -1; 882 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 883 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 884 buf + 6)) 885 reply_len = -1; 886 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 887 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 888 reply_len = -1; 889 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 890 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 891 reply_len = -1; 892 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 893 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 894 reply_len = -1; 895 #ifdef CONFIG_IEEE80211W 896 #ifdef NEED_AP_MLME 897 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 898 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 899 reply_len = -1; 900 #endif /* NEED_AP_MLME */ 901 #endif /* CONFIG_IEEE80211W */ 902 #ifdef CONFIG_WPS 903 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 904 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 905 reply_len = -1; 906 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 907 reply_len = hostapd_ctrl_iface_wps_check_pin( 908 hapd, buf + 14, reply, reply_size); 909 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 910 if (hostapd_wps_button_pushed(hapd, NULL)) 911 reply_len = -1; 912 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 913 if (hostapd_wps_cancel(hapd)) 914 reply_len = -1; 915 #ifdef CONFIG_WPS_OOB 916 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 917 if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8)) 918 reply_len = -1; 919 #endif /* CONFIG_WPS_OOB */ 920 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 921 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 922 reply, reply_size); 923 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 924 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 925 reply_len = -1; 926 #ifdef CONFIG_WPS_NFC 927 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 928 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 929 reply_len = -1; 930 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 931 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 932 hapd, buf + 21, reply, reply_size); 933 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 934 reply_len = hostapd_ctrl_iface_wps_nfc_token( 935 hapd, buf + 14, reply, reply_size); 936 #endif /* CONFIG_WPS_NFC */ 937 #endif /* CONFIG_WPS */ 938 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 939 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 940 reply_len = -1; 941 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 942 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 943 reply_size); 944 } else if (os_strncmp(buf, "SET ", 4) == 0) { 945 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 946 reply_len = -1; 947 } else if (os_strncmp(buf, "GET ", 4) == 0) { 948 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 949 reply_size); 950 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 951 if (hostapd_ctrl_iface_enable(hapd->iface)) 952 reply_len = -1; 953 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 954 if (hostapd_ctrl_iface_reload(hapd->iface)) 955 reply_len = -1; 956 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 957 if (hostapd_ctrl_iface_disable(hapd->iface)) 958 reply_len = -1; 959 } else { 960 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 961 reply_len = 16; 962 } 963 964 if (reply_len < 0) { 965 os_memcpy(reply, "FAIL\n", 5); 966 reply_len = 5; 967 } 968 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 969 os_free(reply); 970 } 971 972 973 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 974 { 975 char *buf; 976 size_t len; 977 978 if (hapd->conf->ctrl_interface == NULL) 979 return NULL; 980 981 len = os_strlen(hapd->conf->ctrl_interface) + 982 os_strlen(hapd->conf->iface) + 2; 983 buf = os_malloc(len); 984 if (buf == NULL) 985 return NULL; 986 987 os_snprintf(buf, len, "%s/%s", 988 hapd->conf->ctrl_interface, hapd->conf->iface); 989 buf[len - 1] = '\0'; 990 return buf; 991 } 992 993 994 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 995 const char *txt, size_t len) 996 { 997 struct hostapd_data *hapd = ctx; 998 if (hapd == NULL) 999 return; 1000 hostapd_ctrl_iface_send(hapd, level, txt, len); 1001 } 1002 1003 1004 int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 1005 { 1006 struct sockaddr_un addr; 1007 int s = -1; 1008 char *fname = NULL; 1009 1010 if (hapd->ctrl_sock > -1) { 1011 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 1012 return 0; 1013 } 1014 1015 if (hapd->conf->ctrl_interface == NULL) 1016 return 0; 1017 1018 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 1019 if (errno == EEXIST) { 1020 wpa_printf(MSG_DEBUG, "Using existing control " 1021 "interface directory."); 1022 } else { 1023 perror("mkdir[ctrl_interface]"); 1024 goto fail; 1025 } 1026 } 1027 1028 if (hapd->conf->ctrl_interface_gid_set && 1029 chown(hapd->conf->ctrl_interface, 0, 1030 hapd->conf->ctrl_interface_gid) < 0) { 1031 perror("chown[ctrl_interface]"); 1032 return -1; 1033 } 1034 1035 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 1036 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 1037 goto fail; 1038 1039 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1040 if (s < 0) { 1041 perror("socket(PF_UNIX)"); 1042 goto fail; 1043 } 1044 1045 os_memset(&addr, 0, sizeof(addr)); 1046 #ifdef __FreeBSD__ 1047 addr.sun_len = sizeof(addr); 1048 #endif /* __FreeBSD__ */ 1049 addr.sun_family = AF_UNIX; 1050 fname = hostapd_ctrl_iface_path(hapd); 1051 if (fname == NULL) 1052 goto fail; 1053 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1054 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1055 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1056 strerror(errno)); 1057 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1058 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1059 " allow connections - assuming it was left" 1060 "over from forced program termination"); 1061 if (unlink(fname) < 0) { 1062 perror("unlink[ctrl_iface]"); 1063 wpa_printf(MSG_ERROR, "Could not unlink " 1064 "existing ctrl_iface socket '%s'", 1065 fname); 1066 goto fail; 1067 } 1068 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1069 0) { 1070 perror("hostapd-ctrl-iface: bind(PF_UNIX)"); 1071 goto fail; 1072 } 1073 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1074 "ctrl_iface socket '%s'", fname); 1075 } else { 1076 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1077 "be in use - cannot override it"); 1078 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1079 "not used anymore", fname); 1080 os_free(fname); 1081 fname = NULL; 1082 goto fail; 1083 } 1084 } 1085 1086 if (hapd->conf->ctrl_interface_gid_set && 1087 chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) { 1088 perror("chown[ctrl_interface/ifname]"); 1089 goto fail; 1090 } 1091 1092 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1093 perror("chmod[ctrl_interface/ifname]"); 1094 goto fail; 1095 } 1096 os_free(fname); 1097 1098 hapd->ctrl_sock = s; 1099 eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 1100 NULL); 1101 hapd->msg_ctx = hapd; 1102 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 1103 1104 return 0; 1105 1106 fail: 1107 if (s >= 0) 1108 close(s); 1109 if (fname) { 1110 unlink(fname); 1111 os_free(fname); 1112 } 1113 return -1; 1114 } 1115 1116 1117 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 1118 { 1119 struct wpa_ctrl_dst *dst, *prev; 1120 1121 if (hapd->ctrl_sock > -1) { 1122 char *fname; 1123 eloop_unregister_read_sock(hapd->ctrl_sock); 1124 close(hapd->ctrl_sock); 1125 hapd->ctrl_sock = -1; 1126 fname = hostapd_ctrl_iface_path(hapd); 1127 if (fname) 1128 unlink(fname); 1129 os_free(fname); 1130 1131 if (hapd->conf->ctrl_interface && 1132 rmdir(hapd->conf->ctrl_interface) < 0) { 1133 if (errno == ENOTEMPTY) { 1134 wpa_printf(MSG_DEBUG, "Control interface " 1135 "directory not empty - leaving it " 1136 "behind"); 1137 } else { 1138 perror("rmdir[ctrl_interface]"); 1139 } 1140 } 1141 } 1142 1143 dst = hapd->ctrl_dst; 1144 while (dst) { 1145 prev = dst; 1146 dst = dst->next; 1147 os_free(prev); 1148 } 1149 } 1150 1151 1152 static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 1153 char *buf) 1154 { 1155 if (hostapd_add_iface(interfaces, buf) < 0) { 1156 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 1157 return -1; 1158 } 1159 return 0; 1160 } 1161 1162 1163 static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 1164 char *buf) 1165 { 1166 if (hostapd_remove_iface(interfaces, buf) < 0) { 1167 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 1168 return -1; 1169 } 1170 return 0; 1171 } 1172 1173 1174 static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 1175 void *sock_ctx) 1176 { 1177 void *interfaces = eloop_ctx; 1178 char buf[256]; 1179 int res; 1180 struct sockaddr_un from; 1181 socklen_t fromlen = sizeof(from); 1182 char reply[24]; 1183 int reply_len; 1184 1185 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1186 (struct sockaddr *) &from, &fromlen); 1187 if (res < 0) { 1188 perror("recvfrom(ctrl_iface)"); 1189 return; 1190 } 1191 buf[res] = '\0'; 1192 1193 os_memcpy(reply, "OK\n", 3); 1194 reply_len = 3; 1195 1196 if (os_strcmp(buf, "PING") == 0) { 1197 os_memcpy(reply, "PONG\n", 5); 1198 reply_len = 5; 1199 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 1200 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 1201 reply_len = -1; 1202 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 1203 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 1204 reply_len = -1; 1205 } else { 1206 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 1207 "ignored"); 1208 reply_len = -1; 1209 } 1210 1211 if (reply_len < 0) { 1212 os_memcpy(reply, "FAIL\n", 5); 1213 reply_len = 5; 1214 } 1215 1216 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 1217 } 1218 1219 1220 static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 1221 { 1222 char *buf; 1223 size_t len; 1224 1225 if (interface->global_iface_path == NULL) 1226 return NULL; 1227 1228 len = os_strlen(interface->global_iface_path) + 1229 os_strlen(interface->global_iface_name) + 2; 1230 buf = os_malloc(len); 1231 if (buf == NULL) 1232 return NULL; 1233 1234 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 1235 interface->global_iface_name); 1236 buf[len - 1] = '\0'; 1237 return buf; 1238 } 1239 1240 1241 int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 1242 { 1243 struct sockaddr_un addr; 1244 int s = -1; 1245 char *fname = NULL; 1246 1247 if (interface->global_iface_path == NULL) { 1248 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 1249 return 0; 1250 } 1251 1252 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 1253 if (errno == EEXIST) { 1254 wpa_printf(MSG_DEBUG, "Using existing control " 1255 "interface directory."); 1256 } else { 1257 perror("mkdir[ctrl_interface]"); 1258 goto fail; 1259 } 1260 } 1261 1262 if (os_strlen(interface->global_iface_path) + 1 + 1263 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 1264 goto fail; 1265 1266 s = socket(PF_UNIX, SOCK_DGRAM, 0); 1267 if (s < 0) { 1268 perror("socket(PF_UNIX)"); 1269 goto fail; 1270 } 1271 1272 os_memset(&addr, 0, sizeof(addr)); 1273 #ifdef __FreeBSD__ 1274 addr.sun_len = sizeof(addr); 1275 #endif /* __FreeBSD__ */ 1276 addr.sun_family = AF_UNIX; 1277 fname = hostapd_global_ctrl_iface_path(interface); 1278 if (fname == NULL) 1279 goto fail; 1280 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 1281 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1282 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 1283 strerror(errno)); 1284 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 1285 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 1286 " allow connections - assuming it was left" 1287 "over from forced program termination"); 1288 if (unlink(fname) < 0) { 1289 perror("unlink[ctrl_iface]"); 1290 wpa_printf(MSG_ERROR, "Could not unlink " 1291 "existing ctrl_iface socket '%s'", 1292 fname); 1293 goto fail; 1294 } 1295 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 1296 0) { 1297 perror("bind(PF_UNIX)"); 1298 goto fail; 1299 } 1300 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1301 "ctrl_iface socket '%s'", fname); 1302 } else { 1303 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1304 "be in use - cannot override it"); 1305 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1306 "not used anymore", fname); 1307 os_free(fname); 1308 fname = NULL; 1309 goto fail; 1310 } 1311 } 1312 1313 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1314 perror("chmod[ctrl_interface/ifname]"); 1315 goto fail; 1316 } 1317 os_free(fname); 1318 1319 interface->global_ctrl_sock = s; 1320 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 1321 interface, NULL); 1322 1323 return 0; 1324 1325 fail: 1326 if (s >= 0) 1327 close(s); 1328 if (fname) { 1329 unlink(fname); 1330 os_free(fname); 1331 } 1332 return -1; 1333 } 1334 1335 1336 void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 1337 { 1338 char *fname = NULL; 1339 1340 if (interfaces->global_ctrl_sock > -1) { 1341 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 1342 close(interfaces->global_ctrl_sock); 1343 interfaces->global_ctrl_sock = -1; 1344 fname = hostapd_global_ctrl_iface_path(interfaces); 1345 if (fname) { 1346 unlink(fname); 1347 os_free(fname); 1348 } 1349 1350 if (interfaces->global_iface_path && 1351 rmdir(interfaces->global_iface_path) < 0) { 1352 if (errno == ENOTEMPTY) { 1353 wpa_printf(MSG_DEBUG, "Control interface " 1354 "directory not empty - leaving it " 1355 "behind"); 1356 } else { 1357 perror("rmdir[ctrl_interface]"); 1358 } 1359 } 1360 os_free(interfaces->global_iface_path); 1361 interfaces->global_iface_path = NULL; 1362 } 1363 } 1364 1365 1366 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 1367 const char *buf, size_t len) 1368 { 1369 struct wpa_ctrl_dst *dst, *next; 1370 struct msghdr msg; 1371 int idx; 1372 struct iovec io[2]; 1373 char levelstr[10]; 1374 1375 dst = hapd->ctrl_dst; 1376 if (hapd->ctrl_sock < 0 || dst == NULL) 1377 return; 1378 1379 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 1380 io[0].iov_base = levelstr; 1381 io[0].iov_len = os_strlen(levelstr); 1382 io[1].iov_base = (char *) buf; 1383 io[1].iov_len = len; 1384 os_memset(&msg, 0, sizeof(msg)); 1385 msg.msg_iov = io; 1386 msg.msg_iovlen = 2; 1387 1388 idx = 0; 1389 while (dst) { 1390 next = dst->next; 1391 if (level >= dst->debug_level) { 1392 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 1393 (u8 *) dst->addr.sun_path, dst->addrlen - 1394 offsetof(struct sockaddr_un, sun_path)); 1395 msg.msg_name = &dst->addr; 1396 msg.msg_namelen = dst->addrlen; 1397 if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { 1398 int _errno = errno; 1399 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 1400 "%d - %s", 1401 idx, errno, strerror(errno)); 1402 dst->errors++; 1403 if (dst->errors > 10 || _errno == ENOENT) { 1404 hostapd_ctrl_iface_detach( 1405 hapd, &dst->addr, 1406 dst->addrlen); 1407 } 1408 } else 1409 dst->errors = 0; 1410 } 1411 idx++; 1412 dst = next; 1413 } 1414 } 1415 1416 #endif /* CONFIG_NATIVE_WINDOWS */ 1417