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