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