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