1 /* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2010, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "utils/includes.h" 16 17 #ifndef CONFIG_NATIVE_WINDOWS 18 19 #include <sys/un.h> 20 #include <sys/stat.h> 21 #include <stddef.h> 22 23 #include "utils/common.h" 24 #include "utils/eloop.h" 25 #include "common/version.h" 26 #include "common/ieee802_11_defs.h" 27 #include "drivers/driver.h" 28 #include "radius/radius_client.h" 29 #include "ap/hostapd.h" 30 #include "ap/ap_config.h" 31 #include "ap/ieee802_1x.h" 32 #include "ap/wpa_auth.h" 33 #include "ap/ieee802_11.h" 34 #include "ap/sta_info.h" 35 #include "ap/accounting.h" 36 #include "ap/wps_hostapd.h" 37 #include "ap/ctrl_iface_ap.h" 38 #include "ap/ap_drv_ops.h" 39 #include "wps/wps_defs.h" 40 #include "wps/wps.h" 41 #include "ctrl_iface.h" 42 43 44 struct wpa_ctrl_dst { 45 struct wpa_ctrl_dst *next; 46 struct sockaddr_un addr; 47 socklen_t addrlen; 48 int debug_level; 49 int errors; 50 }; 51 52 53 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 54 const char *buf, size_t len); 55 56 57 static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 58 struct sockaddr_un *from, 59 socklen_t fromlen) 60 { 61 struct wpa_ctrl_dst *dst; 62 63 dst = os_zalloc(sizeof(*dst)); 64 if (dst == NULL) 65 return -1; 66 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 67 dst->addrlen = fromlen; 68 dst->debug_level = MSG_INFO; 69 dst->next = hapd->ctrl_dst; 70 hapd->ctrl_dst = dst; 71 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 72 (u8 *) from->sun_path, 73 fromlen - offsetof(struct sockaddr_un, sun_path)); 74 return 0; 75 } 76 77 78 static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 79 struct sockaddr_un *from, 80 socklen_t fromlen) 81 { 82 struct wpa_ctrl_dst *dst, *prev = NULL; 83 84 dst = hapd->ctrl_dst; 85 while (dst) { 86 if (fromlen == dst->addrlen && 87 os_memcmp(from->sun_path, dst->addr.sun_path, 88 fromlen - offsetof(struct sockaddr_un, sun_path)) 89 == 0) { 90 if (prev == NULL) 91 hapd->ctrl_dst = dst->next; 92 else 93 prev->next = dst->next; 94 os_free(dst); 95 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 96 (u8 *) from->sun_path, 97 fromlen - 98 offsetof(struct sockaddr_un, sun_path)); 99 return 0; 100 } 101 prev = dst; 102 dst = dst->next; 103 } 104 return -1; 105 } 106 107 108 static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 109 struct sockaddr_un *from, 110 socklen_t fromlen, 111 char *level) 112 { 113 struct wpa_ctrl_dst *dst; 114 115 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 116 117 dst = hapd->ctrl_dst; 118 while (dst) { 119 if (fromlen == dst->addrlen && 120 os_memcmp(from->sun_path, dst->addr.sun_path, 121 fromlen - offsetof(struct sockaddr_un, sun_path)) 122 == 0) { 123 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 124 "level", (u8 *) from->sun_path, fromlen - 125 offsetof(struct sockaddr_un, sun_path)); 126 dst->debug_level = atoi(level); 127 return 0; 128 } 129 dst = dst->next; 130 } 131 132 return -1; 133 } 134 135 136 static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 137 const char *txtaddr) 138 { 139 u8 addr[ETH_ALEN]; 140 struct sta_info *sta; 141 142 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 143 144 if (hwaddr_aton(txtaddr, addr)) 145 return -1; 146 147 sta = ap_get_sta(hapd, addr); 148 if (sta) 149 return 0; 150 151 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 152 "notification", MAC2STR(addr)); 153 sta = ap_sta_add(hapd, addr); 154 if (sta == NULL) 155 return -1; 156 157 hostapd_new_assoc_sta(hapd, sta, 0); 158 return 0; 159 } 160 161 162 #ifdef CONFIG_P2P_MANAGER 163 static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, 164 u8 minor_reason_code, const u8 *addr) 165 { 166 struct ieee80211_mgmt *mgmt; 167 int ret; 168 u8 *pos; 169 170 if (hapd->driver->send_frame == NULL) 171 return -1; 172 173 mgmt = os_zalloc(sizeof(*mgmt) + 100); 174 if (mgmt == NULL) 175 return -1; 176 177 wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor " 178 "reason code %u (stype=%u)", 179 MAC2STR(addr), minor_reason_code, stype); 180 181 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); 182 os_memcpy(mgmt->da, addr, ETH_ALEN); 183 os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); 184 os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); 185 if (stype == WLAN_FC_STYPE_DEAUTH) { 186 mgmt->u.deauth.reason_code = 187 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); 188 pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); 189 } else { 190 mgmt->u.disassoc.reason_code = 191 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); 192 pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); 193 } 194 195 *pos++ = WLAN_EID_VENDOR_SPECIFIC; 196 *pos++ = 4 + 3 + 1; 197 WPA_PUT_BE24(pos, OUI_WFA); 198 pos += 3; 199 *pos++ = P2P_OUI_TYPE; 200 201 *pos++ = P2P_ATTR_MINOR_REASON_CODE; 202 WPA_PUT_LE16(pos, 1); 203 pos += 2; 204 *pos++ = minor_reason_code; 205 206 ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, 207 pos - (u8 *) mgmt, 1); 208 os_free(mgmt); 209 210 return ret < 0 ? -1 : 0; 211 } 212 #endif /* CONFIG_P2P_MANAGER */ 213 214 215 static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, 216 const char *txtaddr) 217 { 218 u8 addr[ETH_ALEN]; 219 struct sta_info *sta; 220 const char *pos; 221 222 wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); 223 224 if (hwaddr_aton(txtaddr, addr)) 225 return -1; 226 227 pos = os_strstr(txtaddr, " test="); 228 if (pos) { 229 struct ieee80211_mgmt mgmt; 230 int encrypt; 231 if (hapd->driver->send_frame == NULL) 232 return -1; 233 pos += 6; 234 encrypt = atoi(pos); 235 os_memset(&mgmt, 0, sizeof(mgmt)); 236 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 237 WLAN_FC_STYPE_DEAUTH); 238 os_memcpy(mgmt.da, addr, ETH_ALEN); 239 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); 240 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); 241 mgmt.u.deauth.reason_code = 242 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); 243 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, 244 IEEE80211_HDRLEN + 245 sizeof(mgmt.u.deauth), 246 encrypt) < 0) 247 return -1; 248 return 0; 249 } 250 251 #ifdef CONFIG_P2P_MANAGER 252 pos = os_strstr(txtaddr, " p2p="); 253 if (pos) { 254 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, 255 atoi(pos + 5), addr); 256 } 257 #endif /* CONFIG_P2P_MANAGER */ 258 259 hostapd_drv_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); 260 sta = ap_get_sta(hapd, addr); 261 if (sta) 262 ap_sta_deauthenticate(hapd, sta, 263 WLAN_REASON_PREV_AUTH_NOT_VALID); 264 else if (addr[0] == 0xff) 265 hostapd_free_stas(hapd); 266 267 return 0; 268 } 269 270 271 static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, 272 const char *txtaddr) 273 { 274 u8 addr[ETH_ALEN]; 275 struct sta_info *sta; 276 const char *pos; 277 278 wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); 279 280 if (hwaddr_aton(txtaddr, addr)) 281 return -1; 282 283 pos = os_strstr(txtaddr, " test="); 284 if (pos) { 285 struct ieee80211_mgmt mgmt; 286 int encrypt; 287 if (hapd->driver->send_frame == NULL) 288 return -1; 289 pos += 6; 290 encrypt = atoi(pos); 291 os_memset(&mgmt, 0, sizeof(mgmt)); 292 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 293 WLAN_FC_STYPE_DISASSOC); 294 os_memcpy(mgmt.da, addr, ETH_ALEN); 295 os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); 296 os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); 297 mgmt.u.disassoc.reason_code = 298 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); 299 if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, 300 IEEE80211_HDRLEN + 301 sizeof(mgmt.u.deauth), 302 encrypt) < 0) 303 return -1; 304 return 0; 305 } 306 307 #ifdef CONFIG_P2P_MANAGER 308 pos = os_strstr(txtaddr, " p2p="); 309 if (pos) { 310 return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, 311 atoi(pos + 5), addr); 312 } 313 #endif /* CONFIG_P2P_MANAGER */ 314 315 hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); 316 sta = ap_get_sta(hapd, addr); 317 if (sta) 318 ap_sta_disassociate(hapd, sta, 319 WLAN_REASON_PREV_AUTH_NOT_VALID); 320 else if (addr[0] == 0xff) 321 hostapd_free_stas(hapd); 322 323 return 0; 324 } 325 326 327 #ifdef CONFIG_IEEE80211W 328 #ifdef NEED_AP_MLME 329 static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 330 const char *txtaddr) 331 { 332 u8 addr[ETH_ALEN]; 333 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 334 335 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 336 337 if (hwaddr_aton(txtaddr, addr) || 338 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 339 return -1; 340 341 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 342 343 return 0; 344 } 345 #endif /* NEED_AP_MLME */ 346 #endif /* CONFIG_IEEE80211W */ 347 348 349 #ifdef CONFIG_WPS 350 static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 351 { 352 char *pin = os_strchr(txt, ' '); 353 char *timeout_txt; 354 int timeout; 355 u8 addr_buf[ETH_ALEN], *addr = NULL; 356 char *pos; 357 358 if (pin == NULL) 359 return -1; 360 *pin++ = '\0'; 361 362 timeout_txt = os_strchr(pin, ' '); 363 if (timeout_txt) { 364 *timeout_txt++ = '\0'; 365 timeout = atoi(timeout_txt); 366 pos = os_strchr(timeout_txt, ' '); 367 if (pos) { 368 *pos++ = '\0'; 369 if (hwaddr_aton(pos, addr_buf) == 0) 370 addr = addr_buf; 371 } 372 } else 373 timeout = 0; 374 375 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 376 } 377 378 379 static int hostapd_ctrl_iface_wps_check_pin( 380 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 381 { 382 char pin[9]; 383 size_t len; 384 char *pos; 385 int ret; 386 387 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 388 (u8 *) cmd, os_strlen(cmd)); 389 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 390 if (*pos < '0' || *pos > '9') 391 continue; 392 pin[len++] = *pos; 393 if (len == 9) { 394 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 395 return -1; 396 } 397 } 398 if (len != 4 && len != 8) { 399 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 400 return -1; 401 } 402 pin[len] = '\0'; 403 404 if (len == 8) { 405 unsigned int pin_val; 406 pin_val = atoi(pin); 407 if (!wps_pin_valid(pin_val)) { 408 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 409 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 410 if (ret < 0 || (size_t) ret >= buflen) 411 return -1; 412 return ret; 413 } 414 } 415 416 ret = os_snprintf(buf, buflen, "%s", pin); 417 if (ret < 0 || (size_t) ret >= buflen) 418 return -1; 419 420 return ret; 421 } 422 423 424 #ifdef CONFIG_WPS_OOB 425 static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) 426 { 427 char *path, *method, *name; 428 429 path = os_strchr(txt, ' '); 430 if (path == NULL) 431 return -1; 432 *path++ = '\0'; 433 434 method = os_strchr(path, ' '); 435 if (method == NULL) 436 return -1; 437 *method++ = '\0'; 438 439 name = os_strchr(method, ' '); 440 if (name != NULL) 441 *name++ = '\0'; 442 443 return hostapd_wps_start_oob(hapd, txt, path, method, name); 444 } 445 #endif /* CONFIG_WPS_OOB */ 446 447 448 static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 449 char *buf, size_t buflen) 450 { 451 int timeout = 300; 452 char *pos; 453 const char *pin_txt; 454 455 pos = os_strchr(txt, ' '); 456 if (pos) 457 *pos++ = '\0'; 458 459 if (os_strcmp(txt, "disable") == 0) { 460 hostapd_wps_ap_pin_disable(hapd); 461 return os_snprintf(buf, buflen, "OK\n"); 462 } 463 464 if (os_strcmp(txt, "random") == 0) { 465 if (pos) 466 timeout = atoi(pos); 467 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 468 if (pin_txt == NULL) 469 return -1; 470 return os_snprintf(buf, buflen, "%s", pin_txt); 471 } 472 473 if (os_strcmp(txt, "get") == 0) { 474 pin_txt = hostapd_wps_ap_pin_get(hapd); 475 if (pin_txt == NULL) 476 return -1; 477 return os_snprintf(buf, buflen, "%s", pin_txt); 478 } 479 480 if (os_strcmp(txt, "set") == 0) { 481 char *pin; 482 if (pos == NULL) 483 return -1; 484 pin = pos; 485 pos = os_strchr(pos, ' '); 486 if (pos) { 487 *pos++ = '\0'; 488 timeout = atoi(pos); 489 } 490 if (os_strlen(pin) > buflen) 491 return -1; 492 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 493 return -1; 494 return os_snprintf(buf, buflen, "%s", pin); 495 } 496 497 return -1; 498 } 499 500 501 static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 502 { 503 char *pos; 504 char *ssid, *auth, *encr = NULL, *key = NULL; 505 506 ssid = txt; 507 pos = os_strchr(txt, ' '); 508 if (!pos) 509 return -1; 510 *pos++ = '\0'; 511 512 auth = pos; 513 pos = os_strchr(pos, ' '); 514 if (pos) { 515 *pos++ = '\0'; 516 encr = pos; 517 pos = os_strchr(pos, ' '); 518 if (pos) { 519 *pos++ = '\0'; 520 key = pos; 521 } 522 } 523 524 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 525 } 526 #endif /* CONFIG_WPS */ 527 528 529 static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 530 char *buf, size_t buflen) 531 { 532 int ret; 533 char *pos, *end; 534 535 pos = buf; 536 end = buf + buflen; 537 538 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 539 "ssid=%s\n", 540 MAC2STR(hapd->own_addr), 541 hapd->conf->ssid.ssid); 542 if (ret < 0 || ret >= end - pos) 543 return pos - buf; 544 pos += ret; 545 546 #ifdef CONFIG_WPS 547 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 548 hapd->conf->wps_state == 0 ? "disabled" : 549 (hapd->conf->wps_state == 1 ? "not configured" : 550 "configured")); 551 if (ret < 0 || ret >= end - pos) 552 return pos - buf; 553 pos += ret; 554 555 if (hapd->conf->wps_state && hapd->conf->wpa && 556 hapd->conf->ssid.wpa_passphrase) { 557 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 558 hapd->conf->ssid.wpa_passphrase); 559 if (ret < 0 || ret >= end - pos) 560 return pos - buf; 561 pos += ret; 562 } 563 564 if (hapd->conf->wps_state && hapd->conf->wpa && 565 hapd->conf->ssid.wpa_psk && 566 hapd->conf->ssid.wpa_psk->group) { 567 char hex[PMK_LEN * 2 + 1]; 568 wpa_snprintf_hex(hex, sizeof(hex), 569 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 570 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 571 if (ret < 0 || ret >= end - pos) 572 return pos - buf; 573 pos += ret; 574 } 575 #endif /* CONFIG_WPS */ 576 577 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 578 ret = os_snprintf(pos, end - pos, "key_mgmt="); 579 if (ret < 0 || ret >= end - pos) 580 return pos - buf; 581 pos += ret; 582 583 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 584 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 585 if (ret < 0 || ret >= end - pos) 586 return pos - buf; 587 pos += ret; 588 } 589 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 590 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 591 if (ret < 0 || ret >= end - pos) 592 return pos - buf; 593 pos += ret; 594 } 595 #ifdef CONFIG_IEEE80211R 596 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 597 ret = os_snprintf(pos, end - pos, "FT-PSK "); 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_FT_IEEE8021X) { 603 ret = os_snprintf(pos, end - pos, "FT-EAP "); 604 if (ret < 0 || ret >= end - pos) 605 return pos - buf; 606 pos += ret; 607 } 608 #endif /* CONFIG_IEEE80211R */ 609 #ifdef CONFIG_IEEE80211W 610 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 611 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 612 if (ret < 0 || ret >= end - pos) 613 return pos - buf; 614 pos += ret; 615 } 616 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 617 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 618 if (ret < 0 || ret >= end - pos) 619 return pos - buf; 620 pos += ret; 621 } 622 #endif /* CONFIG_IEEE80211W */ 623 624 ret = os_snprintf(pos, end - pos, "\n"); 625 if (ret < 0 || ret >= end - pos) 626 return pos - buf; 627 pos += ret; 628 } 629 630 if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_CCMP) { 631 ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n"); 632 if (ret < 0 || ret >= end - pos) 633 return pos - buf; 634 pos += ret; 635 } else if (hapd->conf->wpa && 636 hapd->conf->wpa_group == WPA_CIPHER_TKIP) { 637 ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n"); 638 if (ret < 0 || ret >= end - pos) 639 return pos - buf; 640 pos += ret; 641 } 642 643 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 644 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 645 if (ret < 0 || ret >= end - pos) 646 return pos - buf; 647 pos += ret; 648 649 if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) { 650 ret = os_snprintf(pos, end - pos, "CCMP "); 651 if (ret < 0 || ret >= end - pos) 652 return pos - buf; 653 pos += ret; 654 } 655 if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) { 656 ret = os_snprintf(pos, end - pos, "TKIP "); 657 if (ret < 0 || ret >= end - pos) 658 return pos - buf; 659 pos += ret; 660 } 661 662 ret = os_snprintf(pos, end - pos, "\n"); 663 if (ret < 0 || ret >= end - pos) 664 return pos - buf; 665 pos += ret; 666 } 667 668 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 669 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 670 if (ret < 0 || ret >= end - pos) 671 return pos - buf; 672 pos += ret; 673 674 if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) { 675 ret = os_snprintf(pos, end - pos, "CCMP "); 676 if (ret < 0 || ret >= end - pos) 677 return pos - buf; 678 pos += ret; 679 } 680 if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) { 681 ret = os_snprintf(pos, end - pos, "TKIP "); 682 if (ret < 0 || ret >= end - pos) 683 return pos - buf; 684 pos += ret; 685 } 686 687 ret = os_snprintf(pos, end - pos, "\n"); 688 if (ret < 0 || ret >= end - pos) 689 return pos - buf; 690 pos += ret; 691 } 692 693 return pos - buf; 694 } 695 696 697 static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 698 { 699 char *value; 700 int ret = 0; 701 702 value = os_strchr(cmd, ' '); 703 if (value == NULL) 704 return -1; 705 *value++ = '\0'; 706 707 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 708 if (0) { 709 #ifdef CONFIG_WPS_TESTING 710 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 711 long int val; 712 val = strtol(value, NULL, 0); 713 if (val < 0 || val > 0xff) { 714 ret = -1; 715 wpa_printf(MSG_DEBUG, "WPS: Invalid " 716 "wps_version_number %ld", val); 717 } else { 718 wps_version_number = val; 719 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 720 "version %u.%u", 721 (wps_version_number & 0xf0) >> 4, 722 wps_version_number & 0x0f); 723 hostapd_wps_update_ie(hapd); 724 } 725 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 726 wps_testing_dummy_cred = atoi(value); 727 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 728 wps_testing_dummy_cred); 729 #endif /* CONFIG_WPS_TESTING */ 730 } else { 731 ret = -1; 732 } 733 734 return ret; 735 } 736 737 738 static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 739 char *buf, size_t buflen) 740 { 741 int res; 742 743 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 744 745 if (os_strcmp(cmd, "version") == 0) { 746 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 747 if (res < 0 || (unsigned int) res >= buflen) 748 return -1; 749 return res; 750 } 751 752 return -1; 753 } 754 755 756 static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 757 void *sock_ctx) 758 { 759 struct hostapd_data *hapd = eloop_ctx; 760 char buf[256]; 761 int res; 762 struct sockaddr_un from; 763 socklen_t fromlen = sizeof(from); 764 char *reply; 765 const int reply_size = 4096; 766 int reply_len; 767 int level = MSG_DEBUG; 768 769 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 770 (struct sockaddr *) &from, &fromlen); 771 if (res < 0) { 772 perror("recvfrom(ctrl_iface)"); 773 return; 774 } 775 buf[res] = '\0'; 776 if (os_strcmp(buf, "PING") == 0) 777 level = MSG_EXCESSIVE; 778 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 779 780 reply = os_malloc(reply_size); 781 if (reply == NULL) { 782 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 783 fromlen); 784 return; 785 } 786 787 os_memcpy(reply, "OK\n", 3); 788 reply_len = 3; 789 790 if (os_strcmp(buf, "PING") == 0) { 791 os_memcpy(reply, "PONG\n", 5); 792 reply_len = 5; 793 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 794 if (wpa_debug_reopen_file() < 0) 795 reply_len = -1; 796 } else if (os_strcmp(buf, "MIB") == 0) { 797 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 798 if (reply_len >= 0) { 799 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 800 reply_size - reply_len); 801 if (res < 0) 802 reply_len = -1; 803 else 804 reply_len += res; 805 } 806 if (reply_len >= 0) { 807 res = ieee802_1x_get_mib(hapd, reply + reply_len, 808 reply_size - reply_len); 809 if (res < 0) 810 reply_len = -1; 811 else 812 reply_len += res; 813 } 814 #ifndef CONFIG_NO_RADIUS 815 if (reply_len >= 0) { 816 res = radius_client_get_mib(hapd->radius, 817 reply + reply_len, 818 reply_size - reply_len); 819 if (res < 0) 820 reply_len = -1; 821 else 822 reply_len += res; 823 } 824 #endif /* CONFIG_NO_RADIUS */ 825 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 826 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 827 reply_size); 828 } else if (os_strncmp(buf, "STA ", 4) == 0) { 829 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 830 reply_size); 831 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 832 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 833 reply_size); 834 } else if (os_strcmp(buf, "ATTACH") == 0) { 835 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 836 reply_len = -1; 837 } else if (os_strcmp(buf, "DETACH") == 0) { 838 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 839 reply_len = -1; 840 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 841 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 842 buf + 6)) 843 reply_len = -1; 844 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 845 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 846 reply_len = -1; 847 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 848 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 849 reply_len = -1; 850 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 851 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 852 reply_len = -1; 853 #ifdef CONFIG_IEEE80211W 854 #ifdef NEED_AP_MLME 855 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 856 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 857 reply_len = -1; 858 #endif /* NEED_AP_MLME */ 859 #endif /* CONFIG_IEEE80211W */ 860 #ifdef CONFIG_WPS 861 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 862 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 863 reply_len = -1; 864 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 865 reply_len = hostapd_ctrl_iface_wps_check_pin( 866 hapd, buf + 14, reply, reply_size); 867 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 868 if (hostapd_wps_button_pushed(hapd, NULL)) 869 reply_len = -1; 870 #ifdef CONFIG_WPS_OOB 871 } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { 872 if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8)) 873 reply_len = -1; 874 #endif /* CONFIG_WPS_OOB */ 875 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 876 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 877 reply, reply_size); 878 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 879 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 880 reply_len = -1; 881 #endif /* CONFIG_WPS */ 882 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 883 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 884 reply_size); 885 } else if (os_strncmp(buf, "SET ", 4) == 0) { 886 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 887 reply_len = -1; 888 } else if (os_strncmp(buf, "GET ", 4) == 0) { 889 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 890 reply_size); 891 } else { 892 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 893 reply_len = 16; 894 } 895 896 if (reply_len < 0) { 897 os_memcpy(reply, "FAIL\n", 5); 898 reply_len = 5; 899 } 900 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); 901 os_free(reply); 902 } 903 904 905 static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 906 { 907 char *buf; 908 size_t len; 909 910 if (hapd->conf->ctrl_interface == NULL) 911 return NULL; 912 913 len = os_strlen(hapd->conf->ctrl_interface) + 914 os_strlen(hapd->conf->iface) + 2; 915 buf = os_malloc(len); 916 if (buf == NULL) 917 return NULL; 918 919 os_snprintf(buf, len, "%s/%s", 920 hapd->conf->ctrl_interface, hapd->conf->iface); 921 buf[len - 1] = '\0'; 922 return buf; 923 } 924 925 926 static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, 927 const char *txt, size_t len) 928 { 929 struct hostapd_data *hapd = ctx; 930 if (hapd == NULL) 931 return; 932 hostapd_ctrl_iface_send(hapd, level, txt, len); 933 } 934 935 936 int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 937 { 938 struct sockaddr_un addr; 939 int s = -1; 940 char *fname = NULL; 941 942 hapd->ctrl_sock = -1; 943 944 if (hapd->conf->ctrl_interface == NULL) 945 return 0; 946 947 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 948 if (errno == EEXIST) { 949 wpa_printf(MSG_DEBUG, "Using existing control " 950 "interface directory."); 951 } else { 952 perror("mkdir[ctrl_interface]"); 953 goto fail; 954 } 955 } 956 957 if (hapd->conf->ctrl_interface_gid_set && 958 chown(hapd->conf->ctrl_interface, 0, 959 hapd->conf->ctrl_interface_gid) < 0) { 960 perror("chown[ctrl_interface]"); 961 return -1; 962 } 963 964 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 965 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 966 goto fail; 967 968 s = socket(PF_UNIX, SOCK_DGRAM, 0); 969 if (s < 0) { 970 perror("socket(PF_UNIX)"); 971 goto fail; 972 } 973 974 os_memset(&addr, 0, sizeof(addr)); 975 #ifdef __FreeBSD__ 976 addr.sun_len = sizeof(addr); 977 #endif /* __FreeBSD__ */ 978 addr.sun_family = AF_UNIX; 979 fname = hostapd_ctrl_iface_path(hapd); 980 if (fname == NULL) 981 goto fail; 982 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 983 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 984 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 985 strerror(errno)); 986 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 987 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 988 " allow connections - assuming it was left" 989 "over from forced program termination"); 990 if (unlink(fname) < 0) { 991 perror("unlink[ctrl_iface]"); 992 wpa_printf(MSG_ERROR, "Could not unlink " 993 "existing ctrl_iface socket '%s'", 994 fname); 995 goto fail; 996 } 997 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 998 0) { 999 perror("bind(PF_UNIX)"); 1000 goto fail; 1001 } 1002 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 1003 "ctrl_iface socket '%s'", fname); 1004 } else { 1005 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 1006 "be in use - cannot override it"); 1007 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 1008 "not used anymore", fname); 1009 os_free(fname); 1010 fname = NULL; 1011 goto fail; 1012 } 1013 } 1014 1015 if (hapd->conf->ctrl_interface_gid_set && 1016 chown(fname, 0, hapd->conf->ctrl_interface_gid) < 0) { 1017 perror("chown[ctrl_interface/ifname]"); 1018 goto fail; 1019 } 1020 1021 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 1022 perror("chmod[ctrl_interface/ifname]"); 1023 goto fail; 1024 } 1025 os_free(fname); 1026 1027 hapd->ctrl_sock = s; 1028 eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 1029 NULL); 1030 hapd->msg_ctx = hapd; 1031 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 1032 1033 return 0; 1034 1035 fail: 1036 if (s >= 0) 1037 close(s); 1038 if (fname) { 1039 unlink(fname); 1040 os_free(fname); 1041 } 1042 return -1; 1043 } 1044 1045 1046 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 1047 { 1048 struct wpa_ctrl_dst *dst, *prev; 1049 1050 if (hapd->ctrl_sock > -1) { 1051 char *fname; 1052 eloop_unregister_read_sock(hapd->ctrl_sock); 1053 close(hapd->ctrl_sock); 1054 hapd->ctrl_sock = -1; 1055 fname = hostapd_ctrl_iface_path(hapd); 1056 if (fname) 1057 unlink(fname); 1058 os_free(fname); 1059 1060 if (hapd->conf->ctrl_interface && 1061 rmdir(hapd->conf->ctrl_interface) < 0) { 1062 if (errno == ENOTEMPTY) { 1063 wpa_printf(MSG_DEBUG, "Control interface " 1064 "directory not empty - leaving it " 1065 "behind"); 1066 } else { 1067 perror("rmdir[ctrl_interface]"); 1068 } 1069 } 1070 } 1071 1072 dst = hapd->ctrl_dst; 1073 while (dst) { 1074 prev = dst; 1075 dst = dst->next; 1076 os_free(prev); 1077 } 1078 } 1079 1080 1081 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 1082 const char *buf, size_t len) 1083 { 1084 struct wpa_ctrl_dst *dst, *next; 1085 struct msghdr msg; 1086 int idx; 1087 struct iovec io[2]; 1088 char levelstr[10]; 1089 1090 dst = hapd->ctrl_dst; 1091 if (hapd->ctrl_sock < 0 || dst == NULL) 1092 return; 1093 1094 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 1095 io[0].iov_base = levelstr; 1096 io[0].iov_len = os_strlen(levelstr); 1097 io[1].iov_base = (char *) buf; 1098 io[1].iov_len = len; 1099 os_memset(&msg, 0, sizeof(msg)); 1100 msg.msg_iov = io; 1101 msg.msg_iovlen = 2; 1102 1103 idx = 0; 1104 while (dst) { 1105 next = dst->next; 1106 if (level >= dst->debug_level) { 1107 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 1108 (u8 *) dst->addr.sun_path, dst->addrlen - 1109 offsetof(struct sockaddr_un, sun_path)); 1110 msg.msg_name = &dst->addr; 1111 msg.msg_namelen = dst->addrlen; 1112 if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { 1113 int _errno = errno; 1114 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 1115 "%d - %s", 1116 idx, errno, strerror(errno)); 1117 dst->errors++; 1118 if (dst->errors > 10 || _errno == ENOENT) { 1119 hostapd_ctrl_iface_detach( 1120 hapd, &dst->addr, 1121 dst->addrlen); 1122 } 1123 } else 1124 dst->errors = 0; 1125 } 1126 idx++; 1127 dst = next; 1128 } 1129 } 1130 1131 #endif /* CONFIG_NATIVE_WINDOWS */ 1132