ctrl_iface.c revision 6c0da2bb83f6915d8260912362692d1a742e057b
1/* 2 * hostapd / UNIX domain socket -based control interface 3 * Copyright (c) 2004-2014, 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#ifdef CONFIG_TESTING_OPTIONS 14#include <net/ethernet.h> 15#include <netinet/ip.h> 16#endif /* CONFIG_TESTING_OPTIONS */ 17 18#include <sys/un.h> 19#include <sys/stat.h> 20#include <stddef.h> 21 22#include "utils/common.h" 23#include "utils/eloop.h" 24#include "common/version.h" 25#include "common/ieee802_11_defs.h" 26#include "drivers/driver.h" 27#include "radius/radius_client.h" 28#include "radius/radius_server.h" 29#include "l2_packet/l2_packet.h" 30#include "ap/hostapd.h" 31#include "ap/ap_config.h" 32#include "ap/ieee802_1x.h" 33#include "ap/wpa_auth.h" 34#include "ap/ieee802_11.h" 35#include "ap/sta_info.h" 36#include "ap/wps_hostapd.h" 37#include "ap/ctrl_iface_ap.h" 38#include "ap/ap_drv_ops.h" 39#include "ap/hs20.h" 40#include "ap/wnm_ap.h" 41#include "ap/wpa_auth.h" 42#include "wps/wps_defs.h" 43#include "wps/wps.h" 44#include "config_file.h" 45#include "ctrl_iface.h" 46 47 48struct wpa_ctrl_dst { 49 struct wpa_ctrl_dst *next; 50 struct sockaddr_un addr; 51 socklen_t addrlen; 52 int debug_level; 53 int errors; 54}; 55 56 57static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 58 const char *buf, size_t len); 59 60 61static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, 62 struct sockaddr_un *from, 63 socklen_t fromlen) 64{ 65 struct wpa_ctrl_dst *dst; 66 67 dst = os_zalloc(sizeof(*dst)); 68 if (dst == NULL) 69 return -1; 70 os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); 71 dst->addrlen = fromlen; 72 dst->debug_level = MSG_INFO; 73 dst->next = hapd->ctrl_dst; 74 hapd->ctrl_dst = dst; 75 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", 76 (u8 *) from->sun_path, 77 fromlen - offsetof(struct sockaddr_un, sun_path)); 78 return 0; 79} 80 81 82static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd, 83 struct sockaddr_un *from, 84 socklen_t fromlen) 85{ 86 struct wpa_ctrl_dst *dst, *prev = NULL; 87 88 dst = hapd->ctrl_dst; 89 while (dst) { 90 if (fromlen == dst->addrlen && 91 os_memcmp(from->sun_path, dst->addr.sun_path, 92 fromlen - offsetof(struct sockaddr_un, sun_path)) 93 == 0) { 94 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", 95 (u8 *) from->sun_path, 96 fromlen - 97 offsetof(struct sockaddr_un, sun_path)); 98 if (prev == NULL) 99 hapd->ctrl_dst = dst->next; 100 else 101 prev->next = dst->next; 102 os_free(dst); 103 return 0; 104 } 105 prev = dst; 106 dst = dst->next; 107 } 108 return -1; 109} 110 111 112static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, 113 struct sockaddr_un *from, 114 socklen_t fromlen, 115 char *level) 116{ 117 struct wpa_ctrl_dst *dst; 118 119 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); 120 121 dst = hapd->ctrl_dst; 122 while (dst) { 123 if (fromlen == dst->addrlen && 124 os_memcmp(from->sun_path, dst->addr.sun_path, 125 fromlen - offsetof(struct sockaddr_un, sun_path)) 126 == 0) { 127 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " 128 "level", (u8 *) from->sun_path, fromlen - 129 offsetof(struct sockaddr_un, sun_path)); 130 dst->debug_level = atoi(level); 131 return 0; 132 } 133 dst = dst->next; 134 } 135 136 return -1; 137} 138 139 140static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, 141 const char *txtaddr) 142{ 143 u8 addr[ETH_ALEN]; 144 struct sta_info *sta; 145 146 wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr); 147 148 if (hwaddr_aton(txtaddr, addr)) 149 return -1; 150 151 sta = ap_get_sta(hapd, addr); 152 if (sta) 153 return 0; 154 155 wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface " 156 "notification", MAC2STR(addr)); 157 sta = ap_sta_add(hapd, addr); 158 if (sta == NULL) 159 return -1; 160 161 hostapd_new_assoc_sta(hapd, sta, 0); 162 return 0; 163} 164 165 166#ifdef CONFIG_IEEE80211W 167#ifdef NEED_AP_MLME 168static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, 169 const char *txtaddr) 170{ 171 u8 addr[ETH_ALEN]; 172 u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; 173 174 wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); 175 176 if (hwaddr_aton(txtaddr, addr) || 177 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) 178 return -1; 179 180 ieee802_11_send_sa_query_req(hapd, addr, trans_id); 181 182 return 0; 183} 184#endif /* NEED_AP_MLME */ 185#endif /* CONFIG_IEEE80211W */ 186 187 188#ifdef CONFIG_WPS 189static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) 190{ 191 char *pin = os_strchr(txt, ' '); 192 char *timeout_txt; 193 int timeout; 194 u8 addr_buf[ETH_ALEN], *addr = NULL; 195 char *pos; 196 197 if (pin == NULL) 198 return -1; 199 *pin++ = '\0'; 200 201 timeout_txt = os_strchr(pin, ' '); 202 if (timeout_txt) { 203 *timeout_txt++ = '\0'; 204 timeout = atoi(timeout_txt); 205 pos = os_strchr(timeout_txt, ' '); 206 if (pos) { 207 *pos++ = '\0'; 208 if (hwaddr_aton(pos, addr_buf) == 0) 209 addr = addr_buf; 210 } 211 } else 212 timeout = 0; 213 214 return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout); 215} 216 217 218static int hostapd_ctrl_iface_wps_check_pin( 219 struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) 220{ 221 char pin[9]; 222 size_t len; 223 char *pos; 224 int ret; 225 226 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", 227 (u8 *) cmd, os_strlen(cmd)); 228 for (pos = cmd, len = 0; *pos != '\0'; pos++) { 229 if (*pos < '0' || *pos > '9') 230 continue; 231 pin[len++] = *pos; 232 if (len == 9) { 233 wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); 234 return -1; 235 } 236 } 237 if (len != 4 && len != 8) { 238 wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); 239 return -1; 240 } 241 pin[len] = '\0'; 242 243 if (len == 8) { 244 unsigned int pin_val; 245 pin_val = atoi(pin); 246 if (!wps_pin_valid(pin_val)) { 247 wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); 248 ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); 249 if (os_snprintf_error(buflen, ret)) 250 return -1; 251 return ret; 252 } 253 } 254 255 ret = os_snprintf(buf, buflen, "%s", pin); 256 if (os_snprintf_error(buflen, ret)) 257 return -1; 258 259 return ret; 260} 261 262 263#ifdef CONFIG_WPS_NFC 264static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd, 265 char *pos) 266{ 267 size_t len; 268 struct wpabuf *buf; 269 int ret; 270 271 len = os_strlen(pos); 272 if (len & 0x01) 273 return -1; 274 len /= 2; 275 276 buf = wpabuf_alloc(len); 277 if (buf == NULL) 278 return -1; 279 if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) { 280 wpabuf_free(buf); 281 return -1; 282 } 283 284 ret = hostapd_wps_nfc_tag_read(hapd, buf); 285 wpabuf_free(buf); 286 287 return ret; 288} 289 290 291static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd, 292 char *cmd, char *reply, 293 size_t max_len) 294{ 295 int ndef; 296 struct wpabuf *buf; 297 int res; 298 299 if (os_strcmp(cmd, "WPS") == 0) 300 ndef = 0; 301 else if (os_strcmp(cmd, "NDEF") == 0) 302 ndef = 1; 303 else 304 return -1; 305 306 buf = hostapd_wps_nfc_config_token(hapd, ndef); 307 if (buf == NULL) 308 return -1; 309 310 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 311 wpabuf_len(buf)); 312 reply[res++] = '\n'; 313 reply[res] = '\0'; 314 315 wpabuf_free(buf); 316 317 return res; 318} 319 320 321static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd, 322 char *reply, size_t max_len, 323 int ndef) 324{ 325 struct wpabuf *buf; 326 int res; 327 328 buf = hostapd_wps_nfc_token_gen(hapd, ndef); 329 if (buf == NULL) 330 return -1; 331 332 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 333 wpabuf_len(buf)); 334 reply[res++] = '\n'; 335 reply[res] = '\0'; 336 337 wpabuf_free(buf); 338 339 return res; 340} 341 342 343static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd, 344 char *cmd, char *reply, 345 size_t max_len) 346{ 347 if (os_strcmp(cmd, "WPS") == 0) 348 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 349 max_len, 0); 350 351 if (os_strcmp(cmd, "NDEF") == 0) 352 return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply, 353 max_len, 1); 354 355 if (os_strcmp(cmd, "enable") == 0) 356 return hostapd_wps_nfc_token_enable(hapd); 357 358 if (os_strcmp(cmd, "disable") == 0) { 359 hostapd_wps_nfc_token_disable(hapd); 360 return 0; 361 } 362 363 return -1; 364} 365 366 367static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd, 368 char *cmd, char *reply, 369 size_t max_len) 370{ 371 struct wpabuf *buf; 372 int res; 373 char *pos; 374 int ndef; 375 376 pos = os_strchr(cmd, ' '); 377 if (pos == NULL) 378 return -1; 379 *pos++ = '\0'; 380 381 if (os_strcmp(cmd, "WPS") == 0) 382 ndef = 0; 383 else if (os_strcmp(cmd, "NDEF") == 0) 384 ndef = 1; 385 else 386 return -1; 387 388 if (os_strcmp(pos, "WPS-CR") == 0) 389 buf = hostapd_wps_nfc_hs_cr(hapd, ndef); 390 else 391 buf = NULL; 392 if (buf == NULL) 393 return -1; 394 395 res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf), 396 wpabuf_len(buf)); 397 reply[res++] = '\n'; 398 reply[res] = '\0'; 399 400 wpabuf_free(buf); 401 402 return res; 403} 404 405 406static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd, 407 char *cmd) 408{ 409 size_t len; 410 struct wpabuf *req, *sel; 411 int ret; 412 char *pos, *role, *type, *pos2; 413 414 role = cmd; 415 pos = os_strchr(role, ' '); 416 if (pos == NULL) 417 return -1; 418 *pos++ = '\0'; 419 420 type = pos; 421 pos = os_strchr(type, ' '); 422 if (pos == NULL) 423 return -1; 424 *pos++ = '\0'; 425 426 pos2 = os_strchr(pos, ' '); 427 if (pos2 == NULL) 428 return -1; 429 *pos2++ = '\0'; 430 431 len = os_strlen(pos); 432 if (len & 0x01) 433 return -1; 434 len /= 2; 435 436 req = wpabuf_alloc(len); 437 if (req == NULL) 438 return -1; 439 if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) { 440 wpabuf_free(req); 441 return -1; 442 } 443 444 len = os_strlen(pos2); 445 if (len & 0x01) { 446 wpabuf_free(req); 447 return -1; 448 } 449 len /= 2; 450 451 sel = wpabuf_alloc(len); 452 if (sel == NULL) { 453 wpabuf_free(req); 454 return -1; 455 } 456 if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) { 457 wpabuf_free(req); 458 wpabuf_free(sel); 459 return -1; 460 } 461 462 if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) { 463 ret = hostapd_wps_nfc_report_handover(hapd, req, sel); 464 } else { 465 wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover " 466 "reported: role=%s type=%s", role, type); 467 ret = -1; 468 } 469 wpabuf_free(req); 470 wpabuf_free(sel); 471 472 return ret; 473} 474 475#endif /* CONFIG_WPS_NFC */ 476 477 478static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, 479 char *buf, size_t buflen) 480{ 481 int timeout = 300; 482 char *pos; 483 const char *pin_txt; 484 485 pos = os_strchr(txt, ' '); 486 if (pos) 487 *pos++ = '\0'; 488 489 if (os_strcmp(txt, "disable") == 0) { 490 hostapd_wps_ap_pin_disable(hapd); 491 return os_snprintf(buf, buflen, "OK\n"); 492 } 493 494 if (os_strcmp(txt, "random") == 0) { 495 if (pos) 496 timeout = atoi(pos); 497 pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); 498 if (pin_txt == NULL) 499 return -1; 500 return os_snprintf(buf, buflen, "%s", pin_txt); 501 } 502 503 if (os_strcmp(txt, "get") == 0) { 504 pin_txt = hostapd_wps_ap_pin_get(hapd); 505 if (pin_txt == NULL) 506 return -1; 507 return os_snprintf(buf, buflen, "%s", pin_txt); 508 } 509 510 if (os_strcmp(txt, "set") == 0) { 511 char *pin; 512 if (pos == NULL) 513 return -1; 514 pin = pos; 515 pos = os_strchr(pos, ' '); 516 if (pos) { 517 *pos++ = '\0'; 518 timeout = atoi(pos); 519 } 520 if (os_strlen(pin) > buflen) 521 return -1; 522 if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) 523 return -1; 524 return os_snprintf(buf, buflen, "%s", pin); 525 } 526 527 return -1; 528} 529 530 531static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt) 532{ 533 char *pos; 534 char *ssid, *auth, *encr = NULL, *key = NULL; 535 536 ssid = txt; 537 pos = os_strchr(txt, ' '); 538 if (!pos) 539 return -1; 540 *pos++ = '\0'; 541 542 auth = pos; 543 pos = os_strchr(pos, ' '); 544 if (pos) { 545 *pos++ = '\0'; 546 encr = pos; 547 pos = os_strchr(pos, ' '); 548 if (pos) { 549 *pos++ = '\0'; 550 key = pos; 551 } 552 } 553 554 return hostapd_wps_config_ap(hapd, ssid, auth, encr, key); 555} 556 557 558static const char * pbc_status_str(enum pbc_status status) 559{ 560 switch (status) { 561 case WPS_PBC_STATUS_DISABLE: 562 return "Disabled"; 563 case WPS_PBC_STATUS_ACTIVE: 564 return "Active"; 565 case WPS_PBC_STATUS_TIMEOUT: 566 return "Timed-out"; 567 case WPS_PBC_STATUS_OVERLAP: 568 return "Overlap"; 569 default: 570 return "Unknown"; 571 } 572} 573 574 575static int hostapd_ctrl_iface_wps_get_status(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, "PBC Status: %s\n", 585 pbc_status_str(hapd->wps_stats.pbc_status)); 586 587 if (os_snprintf_error(end - pos, ret)) 588 return pos - buf; 589 pos += ret; 590 591 ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n", 592 (hapd->wps_stats.status == WPS_STATUS_SUCCESS ? 593 "Success": 594 (hapd->wps_stats.status == WPS_STATUS_FAILURE ? 595 "Failed" : "None"))); 596 597 if (os_snprintf_error(end - pos, ret)) 598 return pos - buf; 599 pos += ret; 600 601 /* If status == Failure - Add possible Reasons */ 602 if(hapd->wps_stats.status == WPS_STATUS_FAILURE && 603 hapd->wps_stats.failure_reason > 0) { 604 ret = os_snprintf(pos, end - pos, 605 "Failure Reason: %s\n", 606 wps_ei_str(hapd->wps_stats.failure_reason)); 607 608 if (os_snprintf_error(end - pos, ret)) 609 return pos - buf; 610 pos += ret; 611 } 612 613 if (hapd->wps_stats.status) { 614 ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n", 615 MAC2STR(hapd->wps_stats.peer_addr)); 616 617 if (os_snprintf_error(end - pos, ret)) 618 return pos - buf; 619 pos += ret; 620 } 621 622 return pos - buf; 623} 624 625#endif /* CONFIG_WPS */ 626 627#ifdef CONFIG_HS20 628 629static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd, 630 const char *cmd) 631{ 632 u8 addr[ETH_ALEN]; 633 const char *url; 634 635 if (hwaddr_aton(cmd, addr)) 636 return -1; 637 url = cmd + 17; 638 if (*url == '\0') { 639 url = NULL; 640 } else { 641 if (*url != ' ') 642 return -1; 643 url++; 644 if (*url == '\0') 645 url = NULL; 646 } 647 648 return hs20_send_wnm_notification(hapd, addr, 1, url); 649} 650 651 652static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd, 653 const char *cmd) 654{ 655 u8 addr[ETH_ALEN]; 656 int code, reauth_delay, ret; 657 const char *pos; 658 size_t url_len; 659 struct wpabuf *req; 660 661 /* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */ 662 if (hwaddr_aton(cmd, addr)) 663 return -1; 664 665 pos = os_strchr(cmd, ' '); 666 if (pos == NULL) 667 return -1; 668 pos++; 669 code = atoi(pos); 670 671 pos = os_strchr(pos, ' '); 672 if (pos == NULL) 673 return -1; 674 pos++; 675 reauth_delay = atoi(pos); 676 677 url_len = 0; 678 pos = os_strchr(pos, ' '); 679 if (pos) { 680 pos++; 681 url_len = os_strlen(pos); 682 } 683 684 req = wpabuf_alloc(4 + url_len); 685 if (req == NULL) 686 return -1; 687 wpabuf_put_u8(req, code); 688 wpabuf_put_le16(req, reauth_delay); 689 wpabuf_put_u8(req, url_len); 690 if (pos) 691 wpabuf_put_data(req, pos, url_len); 692 693 wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR 694 " to indicate imminent deauthentication (code=%d " 695 "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay); 696 ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req); 697 wpabuf_free(req); 698 return ret; 699} 700 701#endif /* CONFIG_HS20 */ 702 703 704#ifdef CONFIG_INTERWORKING 705 706static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd, 707 const char *cmd) 708{ 709 u8 qos_map_set[16 + 2 * 21], count = 0; 710 const char *pos = cmd; 711 int val, ret; 712 713 for (;;) { 714 if (count == sizeof(qos_map_set)) { 715 wpa_printf(MSG_ERROR, "Too many qos_map_set parameters"); 716 return -1; 717 } 718 719 val = atoi(pos); 720 if (val < 0 || val > 255) { 721 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 722 return -1; 723 } 724 725 qos_map_set[count++] = val; 726 pos = os_strchr(pos, ','); 727 if (!pos) 728 break; 729 pos++; 730 } 731 732 if (count < 16 || count & 1) { 733 wpa_printf(MSG_INFO, "Invalid QoS Map Set"); 734 return -1; 735 } 736 737 ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count); 738 if (ret) { 739 wpa_printf(MSG_INFO, "Failed to set QoS Map Set"); 740 return -1; 741 } 742 743 os_memcpy(hapd->conf->qos_map_set, qos_map_set, count); 744 hapd->conf->qos_map_set_len = count; 745 746 return 0; 747} 748 749 750static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, 751 const char *cmd) 752{ 753 u8 addr[ETH_ALEN]; 754 struct sta_info *sta; 755 struct wpabuf *buf; 756 u8 *qos_map_set = hapd->conf->qos_map_set; 757 u8 qos_map_set_len = hapd->conf->qos_map_set_len; 758 int ret; 759 760 if (!qos_map_set_len) { 761 wpa_printf(MSG_INFO, "QoS Map Set is not set"); 762 return -1; 763 } 764 765 if (hwaddr_aton(cmd, addr)) 766 return -1; 767 768 sta = ap_get_sta(hapd, addr); 769 if (sta == NULL) { 770 wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " 771 "for QoS Map Configuration message", 772 MAC2STR(addr)); 773 return -1; 774 } 775 776 if (!sta->qos_map_enabled) { 777 wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate " 778 "support for QoS Map", MAC2STR(addr)); 779 return -1; 780 } 781 782 buf = wpabuf_alloc(2 + 2 + qos_map_set_len); 783 if (buf == NULL) 784 return -1; 785 786 wpabuf_put_u8(buf, WLAN_ACTION_QOS); 787 wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG); 788 789 /* QoS Map Set Element */ 790 wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET); 791 wpabuf_put_u8(buf, qos_map_set_len); 792 wpabuf_put_data(buf, qos_map_set, qos_map_set_len); 793 794 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 795 wpabuf_head(buf), wpabuf_len(buf)); 796 wpabuf_free(buf); 797 798 return ret; 799} 800 801#endif /* CONFIG_INTERWORKING */ 802 803 804#ifdef CONFIG_WNM 805 806static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd, 807 const char *cmd) 808{ 809 u8 addr[ETH_ALEN]; 810 int disassoc_timer; 811 struct sta_info *sta; 812 813 if (hwaddr_aton(cmd, addr)) 814 return -1; 815 if (cmd[17] != ' ') 816 return -1; 817 disassoc_timer = atoi(cmd + 17); 818 819 sta = ap_get_sta(hapd, addr); 820 if (sta == NULL) { 821 wpa_printf(MSG_DEBUG, "Station " MACSTR 822 " not found for disassociation imminent message", 823 MAC2STR(addr)); 824 return -1; 825 } 826 827 return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer); 828} 829 830 831static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, 832 const char *cmd) 833{ 834 u8 addr[ETH_ALEN]; 835 const char *url, *timerstr; 836 int disassoc_timer; 837 struct sta_info *sta; 838 839 if (hwaddr_aton(cmd, addr)) 840 return -1; 841 842 sta = ap_get_sta(hapd, addr); 843 if (sta == NULL) { 844 wpa_printf(MSG_DEBUG, "Station " MACSTR 845 " not found for ESS disassociation imminent message", 846 MAC2STR(addr)); 847 return -1; 848 } 849 850 timerstr = cmd + 17; 851 if (*timerstr != ' ') 852 return -1; 853 timerstr++; 854 disassoc_timer = atoi(timerstr); 855 if (disassoc_timer < 0 || disassoc_timer > 65535) 856 return -1; 857 858 url = os_strchr(timerstr, ' '); 859 if (url == NULL) 860 return -1; 861 url++; 862 863 return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); 864} 865 866 867static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd, 868 const char *cmd) 869{ 870 u8 addr[ETH_ALEN]; 871 const char *pos, *end; 872 int disassoc_timer = 0; 873 struct sta_info *sta; 874 u8 req_mode = 0, valid_int = 0x01; 875 u8 bss_term_dur[12]; 876 char *url = NULL; 877 int ret; 878 u8 nei_rep[1000]; 879 u8 *nei_pos = nei_rep; 880 881 if (hwaddr_aton(cmd, addr)) { 882 wpa_printf(MSG_DEBUG, "Invalid STA MAC address"); 883 return -1; 884 } 885 886 sta = ap_get_sta(hapd, addr); 887 if (sta == NULL) { 888 wpa_printf(MSG_DEBUG, "Station " MACSTR 889 " not found for BSS TM Request message", 890 MAC2STR(addr)); 891 return -1; 892 } 893 894 pos = os_strstr(cmd, " disassoc_timer="); 895 if (pos) { 896 pos += 16; 897 disassoc_timer = atoi(pos); 898 if (disassoc_timer < 0 || disassoc_timer > 65535) { 899 wpa_printf(MSG_DEBUG, "Invalid disassoc_timer"); 900 return -1; 901 } 902 } 903 904 pos = os_strstr(cmd, " valid_int="); 905 if (pos) { 906 pos += 11; 907 valid_int = atoi(pos); 908 } 909 910 pos = os_strstr(cmd, " bss_term="); 911 if (pos) { 912 pos += 10; 913 req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED; 914 /* TODO: TSF configurable/learnable */ 915 bss_term_dur[0] = 4; /* Subelement ID */ 916 bss_term_dur[1] = 10; /* Length */ 917 os_memset(bss_term_dur, 2, 8); 918 end = os_strchr(pos, ','); 919 if (end == NULL) { 920 wpa_printf(MSG_DEBUG, "Invalid bss_term data"); 921 return -1; 922 } 923 end++; 924 WPA_PUT_LE16(&bss_term_dur[10], atoi(end)); 925 } 926 927 928 /* 929 * BSS Transition Candidate List Entries - Neighbor Report elements 930 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>, 931 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>] 932 */ 933 pos = cmd; 934 while (pos) { 935 u8 *nei_start; 936 long int val; 937 char *endptr, *tmp; 938 939 pos = os_strstr(pos, " neighbor="); 940 if (!pos) 941 break; 942 if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) { 943 wpa_printf(MSG_DEBUG, 944 "Not enough room for additional neighbor"); 945 return -1; 946 } 947 pos += 10; 948 949 nei_start = nei_pos; 950 *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT; 951 nei_pos++; /* length to be filled in */ 952 953 if (hwaddr_aton(pos, nei_pos)) { 954 wpa_printf(MSG_DEBUG, "Invalid BSSID"); 955 return -1; 956 } 957 nei_pos += ETH_ALEN; 958 pos += 17; 959 if (*pos != ',') { 960 wpa_printf(MSG_DEBUG, "Missing BSSID Information"); 961 return -1; 962 } 963 pos++; 964 965 val = strtol(pos, &endptr, 0); 966 WPA_PUT_LE32(nei_pos, val); 967 nei_pos += 4; 968 if (*endptr != ',') { 969 wpa_printf(MSG_DEBUG, "Missing Operating Class"); 970 return -1; 971 } 972 pos = endptr + 1; 973 974 *nei_pos++ = atoi(pos); /* Operating Class */ 975 pos = os_strchr(pos, ','); 976 if (pos == NULL) { 977 wpa_printf(MSG_DEBUG, "Missing Channel Number"); 978 return -1; 979 } 980 pos++; 981 982 *nei_pos++ = atoi(pos); /* Channel Number */ 983 pos = os_strchr(pos, ','); 984 if (pos == NULL) { 985 wpa_printf(MSG_DEBUG, "Missing PHY Type"); 986 return -1; 987 } 988 pos++; 989 990 *nei_pos++ = atoi(pos); /* PHY Type */ 991 end = os_strchr(pos, ' '); 992 tmp = os_strchr(pos, ','); 993 if (tmp && (!end || tmp < end)) { 994 /* Optional Subelements (hexdump) */ 995 size_t len; 996 997 pos = tmp + 1; 998 end = os_strchr(pos, ' '); 999 if (end) 1000 len = end - pos; 1001 else 1002 len = os_strlen(pos); 1003 if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) { 1004 wpa_printf(MSG_DEBUG, 1005 "Not enough room for neighbor subelements"); 1006 return -1; 1007 } 1008 if (len & 0x01 || 1009 hexstr2bin(pos, nei_pos, len / 2) < 0) { 1010 wpa_printf(MSG_DEBUG, 1011 "Invalid neighbor subelement info"); 1012 return -1; 1013 } 1014 nei_pos += len / 2; 1015 pos = end; 1016 } 1017 1018 nei_start[1] = nei_pos - nei_start - 2; 1019 } 1020 1021 pos = os_strstr(cmd, " url="); 1022 if (pos) { 1023 size_t len; 1024 pos += 5; 1025 end = os_strchr(pos, ' '); 1026 if (end) 1027 len = end - pos; 1028 else 1029 len = os_strlen(pos); 1030 url = os_malloc(len + 1); 1031 if (url == NULL) 1032 return -1; 1033 os_memcpy(url, pos, len); 1034 url[len] = '\0'; 1035 req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; 1036 } 1037 1038 if (os_strstr(cmd, " pref=1")) 1039 req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED; 1040 if (os_strstr(cmd, " abridged=1")) 1041 req_mode |= WNM_BSS_TM_REQ_ABRIDGED; 1042 if (os_strstr(cmd, " disassoc_imminent=1")) 1043 req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT; 1044 1045 ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, 1046 valid_int, bss_term_dur, url, 1047 nei_pos > nei_rep ? nei_rep : NULL, 1048 nei_pos - nei_rep); 1049 os_free(url); 1050 return ret; 1051} 1052 1053#endif /* CONFIG_WNM */ 1054 1055 1056static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, 1057 char *buf, size_t buflen) 1058{ 1059 int ret; 1060 char *pos, *end; 1061 1062 pos = buf; 1063 end = buf + buflen; 1064 1065 ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" 1066 "ssid=%s\n", 1067 MAC2STR(hapd->own_addr), 1068 wpa_ssid_txt(hapd->conf->ssid.ssid, 1069 hapd->conf->ssid.ssid_len)); 1070 if (os_snprintf_error(end - pos, ret)) 1071 return pos - buf; 1072 pos += ret; 1073 1074#ifdef CONFIG_WPS 1075 ret = os_snprintf(pos, end - pos, "wps_state=%s\n", 1076 hapd->conf->wps_state == 0 ? "disabled" : 1077 (hapd->conf->wps_state == 1 ? "not configured" : 1078 "configured")); 1079 if (os_snprintf_error(end - pos, ret)) 1080 return pos - buf; 1081 pos += ret; 1082 1083 if (hapd->conf->wps_state && hapd->conf->wpa && 1084 hapd->conf->ssid.wpa_passphrase) { 1085 ret = os_snprintf(pos, end - pos, "passphrase=%s\n", 1086 hapd->conf->ssid.wpa_passphrase); 1087 if (os_snprintf_error(end - pos, ret)) 1088 return pos - buf; 1089 pos += ret; 1090 } 1091 1092 if (hapd->conf->wps_state && hapd->conf->wpa && 1093 hapd->conf->ssid.wpa_psk && 1094 hapd->conf->ssid.wpa_psk->group) { 1095 char hex[PMK_LEN * 2 + 1]; 1096 wpa_snprintf_hex(hex, sizeof(hex), 1097 hapd->conf->ssid.wpa_psk->psk, PMK_LEN); 1098 ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); 1099 if (os_snprintf_error(end - pos, ret)) 1100 return pos - buf; 1101 pos += ret; 1102 } 1103#endif /* CONFIG_WPS */ 1104 1105 if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { 1106 ret = os_snprintf(pos, end - pos, "key_mgmt="); 1107 if (os_snprintf_error(end - pos, ret)) 1108 return pos - buf; 1109 pos += ret; 1110 1111 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { 1112 ret = os_snprintf(pos, end - pos, "WPA-PSK "); 1113 if (os_snprintf_error(end - pos, ret)) 1114 return pos - buf; 1115 pos += ret; 1116 } 1117 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { 1118 ret = os_snprintf(pos, end - pos, "WPA-EAP "); 1119 if (os_snprintf_error(end - pos, ret)) 1120 return pos - buf; 1121 pos += ret; 1122 } 1123#ifdef CONFIG_IEEE80211R 1124 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { 1125 ret = os_snprintf(pos, end - pos, "FT-PSK "); 1126 if (os_snprintf_error(end - pos, ret)) 1127 return pos - buf; 1128 pos += ret; 1129 } 1130 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { 1131 ret = os_snprintf(pos, end - pos, "FT-EAP "); 1132 if (os_snprintf_error(end - pos, ret)) 1133 return pos - buf; 1134 pos += ret; 1135 } 1136#ifdef CONFIG_SAE 1137 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { 1138 ret = os_snprintf(pos, end - pos, "FT-SAE "); 1139 if (os_snprintf_error(end - pos, ret)) 1140 return pos - buf; 1141 pos += ret; 1142 } 1143#endif /* CONFIG_SAE */ 1144#endif /* CONFIG_IEEE80211R */ 1145#ifdef CONFIG_IEEE80211W 1146 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { 1147 ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); 1148 if (os_snprintf_error(end - pos, ret)) 1149 return pos - buf; 1150 pos += ret; 1151 } 1152 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { 1153 ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); 1154 if (os_snprintf_error(end - pos, ret)) 1155 return pos - buf; 1156 pos += ret; 1157 } 1158#endif /* CONFIG_IEEE80211W */ 1159#ifdef CONFIG_SAE 1160 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { 1161 ret = os_snprintf(pos, end - pos, "SAE "); 1162 if (os_snprintf_error(end - pos, ret)) 1163 return pos - buf; 1164 pos += ret; 1165 } 1166#endif /* CONFIG_SAE */ 1167 if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { 1168 ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B "); 1169 if (os_snprintf_error(end - pos, ret)) 1170 return pos - buf; 1171 pos += ret; 1172 } 1173 1174 ret = os_snprintf(pos, end - pos, "\n"); 1175 if (os_snprintf_error(end - pos, ret)) 1176 return pos - buf; 1177 pos += ret; 1178 } 1179 1180 if (hapd->conf->wpa) { 1181 ret = os_snprintf(pos, end - pos, "group_cipher=%s\n", 1182 wpa_cipher_txt(hapd->conf->wpa_group)); 1183 if (os_snprintf_error(end - pos, ret)) 1184 return pos - buf; 1185 pos += ret; 1186 } 1187 1188 if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { 1189 ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); 1190 if (os_snprintf_error(end - pos, ret)) 1191 return pos - buf; 1192 pos += ret; 1193 1194 ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise, 1195 " "); 1196 if (ret < 0) 1197 return pos - buf; 1198 pos += ret; 1199 1200 ret = os_snprintf(pos, end - pos, "\n"); 1201 if (os_snprintf_error(end - pos, ret)) 1202 return pos - buf; 1203 pos += ret; 1204 } 1205 1206 if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { 1207 ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); 1208 if (os_snprintf_error(end - pos, ret)) 1209 return pos - buf; 1210 pos += ret; 1211 1212 ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise, 1213 " "); 1214 if (ret < 0) 1215 return pos - buf; 1216 pos += ret; 1217 1218 ret = os_snprintf(pos, end - pos, "\n"); 1219 if (os_snprintf_error(end - pos, ret)) 1220 return pos - buf; 1221 pos += ret; 1222 } 1223 1224 return pos - buf; 1225} 1226 1227 1228static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) 1229{ 1230 char *value; 1231 int ret = 0; 1232 1233 value = os_strchr(cmd, ' '); 1234 if (value == NULL) 1235 return -1; 1236 *value++ = '\0'; 1237 1238 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); 1239 if (0) { 1240#ifdef CONFIG_WPS_TESTING 1241 } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { 1242 long int val; 1243 val = strtol(value, NULL, 0); 1244 if (val < 0 || val > 0xff) { 1245 ret = -1; 1246 wpa_printf(MSG_DEBUG, "WPS: Invalid " 1247 "wps_version_number %ld", val); 1248 } else { 1249 wps_version_number = val; 1250 wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " 1251 "version %u.%u", 1252 (wps_version_number & 0xf0) >> 4, 1253 wps_version_number & 0x0f); 1254 hostapd_wps_update_ie(hapd); 1255 } 1256 } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { 1257 wps_testing_dummy_cred = atoi(value); 1258 wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", 1259 wps_testing_dummy_cred); 1260 } else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) { 1261 wps_corrupt_pkhash = atoi(value); 1262 wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d", 1263 wps_corrupt_pkhash); 1264#endif /* CONFIG_WPS_TESTING */ 1265#ifdef CONFIG_INTERWORKING 1266 } else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) { 1267 int val = atoi(value); 1268 if (val <= 0) 1269 ret = -1; 1270 else 1271 hapd->gas_frag_limit = val; 1272#endif /* CONFIG_INTERWORKING */ 1273#ifdef CONFIG_TESTING_OPTIONS 1274 } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { 1275 hapd->ext_mgmt_frame_handling = atoi(value); 1276 } else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) { 1277 hapd->ext_eapol_frame_io = atoi(value); 1278#endif /* CONFIG_TESTING_OPTIONS */ 1279 } else { 1280 struct sta_info *sta; 1281 int vlan_id; 1282 1283 ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value); 1284 if (ret) 1285 return ret; 1286 1287 if (os_strcasecmp(cmd, "deny_mac_file") == 0) { 1288 for (sta = hapd->sta_list; sta; sta = sta->next) { 1289 if (hostapd_maclist_found( 1290 hapd->conf->deny_mac, 1291 hapd->conf->num_deny_mac, sta->addr, 1292 &vlan_id) && 1293 (!vlan_id || vlan_id == sta->vlan_id)) 1294 ap_sta_disconnect( 1295 hapd, sta, sta->addr, 1296 WLAN_REASON_UNSPECIFIED); 1297 } 1298 } else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED && 1299 os_strcasecmp(cmd, "accept_mac_file") == 0) { 1300 for (sta = hapd->sta_list; sta; sta = sta->next) { 1301 if (!hostapd_maclist_found( 1302 hapd->conf->accept_mac, 1303 hapd->conf->num_accept_mac, 1304 sta->addr, &vlan_id) || 1305 (vlan_id && vlan_id != sta->vlan_id)) 1306 ap_sta_disconnect( 1307 hapd, sta, sta->addr, 1308 WLAN_REASON_UNSPECIFIED); 1309 } 1310 } 1311 } 1312 1313 return ret; 1314} 1315 1316 1317static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd, 1318 char *buf, size_t buflen) 1319{ 1320 int res; 1321 1322 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd); 1323 1324 if (os_strcmp(cmd, "version") == 0) { 1325 res = os_snprintf(buf, buflen, "%s", VERSION_STR); 1326 if (os_snprintf_error(buflen, res)) 1327 return -1; 1328 return res; 1329 } 1330 1331 return -1; 1332} 1333 1334 1335static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface) 1336{ 1337 if (hostapd_enable_iface(iface) < 0) { 1338 wpa_printf(MSG_ERROR, "Enabling of interface failed"); 1339 return -1; 1340 } 1341 return 0; 1342} 1343 1344 1345static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface) 1346{ 1347 if (hostapd_reload_iface(iface) < 0) { 1348 wpa_printf(MSG_ERROR, "Reloading of interface failed"); 1349 return -1; 1350 } 1351 return 0; 1352} 1353 1354 1355static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) 1356{ 1357 if (hostapd_disable_iface(iface) < 0) { 1358 wpa_printf(MSG_ERROR, "Disabling of interface failed"); 1359 return -1; 1360 } 1361 return 0; 1362} 1363 1364 1365#ifdef CONFIG_TESTING_OPTIONS 1366 1367static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) 1368{ 1369 union wpa_event_data data; 1370 char *pos, *param; 1371 enum wpa_event_type event; 1372 1373 wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd); 1374 1375 os_memset(&data, 0, sizeof(data)); 1376 1377 param = os_strchr(cmd, ' '); 1378 if (param == NULL) 1379 return -1; 1380 *param++ = '\0'; 1381 1382 if (os_strcmp(cmd, "DETECTED") == 0) 1383 event = EVENT_DFS_RADAR_DETECTED; 1384 else if (os_strcmp(cmd, "CAC-FINISHED") == 0) 1385 event = EVENT_DFS_CAC_FINISHED; 1386 else if (os_strcmp(cmd, "CAC-ABORTED") == 0) 1387 event = EVENT_DFS_CAC_ABORTED; 1388 else if (os_strcmp(cmd, "NOP-FINISHED") == 0) 1389 event = EVENT_DFS_NOP_FINISHED; 1390 else { 1391 wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s", 1392 cmd); 1393 return -1; 1394 } 1395 1396 pos = os_strstr(param, "freq="); 1397 if (pos) 1398 data.dfs_event.freq = atoi(pos + 5); 1399 1400 pos = os_strstr(param, "ht_enabled=1"); 1401 if (pos) 1402 data.dfs_event.ht_enabled = 1; 1403 1404 pos = os_strstr(param, "chan_offset="); 1405 if (pos) 1406 data.dfs_event.chan_offset = atoi(pos + 12); 1407 1408 pos = os_strstr(param, "chan_width="); 1409 if (pos) 1410 data.dfs_event.chan_width = atoi(pos + 11); 1411 1412 pos = os_strstr(param, "cf1="); 1413 if (pos) 1414 data.dfs_event.cf1 = atoi(pos + 4); 1415 1416 pos = os_strstr(param, "cf2="); 1417 if (pos) 1418 data.dfs_event.cf2 = atoi(pos + 4); 1419 1420 wpa_supplicant_event(hapd, event, &data); 1421 1422 return 0; 1423} 1424 1425 1426static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd) 1427{ 1428 size_t len; 1429 u8 *buf; 1430 int res; 1431 1432 wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd); 1433 1434 len = os_strlen(cmd); 1435 if (len & 1) 1436 return -1; 1437 len /= 2; 1438 1439 buf = os_malloc(len); 1440 if (buf == NULL) 1441 return -1; 1442 1443 if (hexstr2bin(cmd, buf, len) < 0) { 1444 os_free(buf); 1445 return -1; 1446 } 1447 1448 res = hostapd_drv_send_mlme(hapd, buf, len, 0); 1449 os_free(buf); 1450 return res; 1451} 1452 1453 1454static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd) 1455{ 1456 char *pos; 1457 u8 src[ETH_ALEN], *buf; 1458 int used; 1459 size_t len; 1460 1461 wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd); 1462 1463 pos = cmd; 1464 used = hwaddr_aton2(pos, src); 1465 if (used < 0) 1466 return -1; 1467 pos += used; 1468 while (*pos == ' ') 1469 pos++; 1470 1471 len = os_strlen(pos); 1472 if (len & 1) 1473 return -1; 1474 len /= 2; 1475 1476 buf = os_malloc(len); 1477 if (buf == NULL) 1478 return -1; 1479 1480 if (hexstr2bin(pos, buf, len) < 0) { 1481 os_free(buf); 1482 return -1; 1483 } 1484 1485 ieee802_1x_receive(hapd, src, buf, len); 1486 os_free(buf); 1487 1488 return 0; 1489} 1490 1491 1492static u16 ipv4_hdr_checksum(const void *buf, size_t len) 1493{ 1494 size_t i; 1495 u32 sum = 0; 1496 const u16 *pos = buf; 1497 1498 for (i = 0; i < len / 2; i++) 1499 sum += *pos++; 1500 1501 while (sum >> 16) 1502 sum = (sum & 0xffff) + (sum >> 16); 1503 1504 return sum ^ 0xffff; 1505} 1506 1507 1508#define HWSIM_PACKETLEN 1500 1509#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header)) 1510 1511void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, 1512 size_t len) 1513{ 1514 struct hostapd_data *hapd = ctx; 1515 const struct ether_header *eth; 1516 const struct iphdr *ip; 1517 const u8 *pos; 1518 unsigned int i; 1519 1520 if (len != HWSIM_PACKETLEN) 1521 return; 1522 1523 eth = (const struct ether_header *) buf; 1524 ip = (const struct iphdr *) (eth + 1); 1525 pos = (const u8 *) (ip + 1); 1526 1527 if (ip->ihl != 5 || ip->version != 4 || 1528 ntohs(ip->tot_len) != HWSIM_IP_LEN) 1529 return; 1530 1531 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) { 1532 if (*pos != (u8) i) 1533 return; 1534 pos++; 1535 } 1536 1537 wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR, 1538 MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost)); 1539} 1540 1541 1542static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd, 1543 char *cmd) 1544{ 1545 int enabled = atoi(cmd); 1546 char *pos; 1547 const char *ifname; 1548 1549 if (!enabled) { 1550 if (hapd->l2_test) { 1551 l2_packet_deinit(hapd->l2_test); 1552 hapd->l2_test = NULL; 1553 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, 1554 "test data: Disabled"); 1555 } 1556 return 0; 1557 } 1558 1559 if (hapd->l2_test) 1560 return 0; 1561 1562 pos = os_strstr(cmd, " ifname="); 1563 if (pos) 1564 ifname = pos + 8; 1565 else 1566 ifname = hapd->conf->iface; 1567 1568 hapd->l2_test = l2_packet_init(ifname, hapd->own_addr, 1569 ETHERTYPE_IP, hostapd_data_test_rx, 1570 hapd, 1); 1571 if (hapd->l2_test == NULL) 1572 return -1; 1573 1574 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled"); 1575 1576 return 0; 1577} 1578 1579 1580static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd) 1581{ 1582 u8 dst[ETH_ALEN], src[ETH_ALEN]; 1583 char *pos; 1584 int used; 1585 long int val; 1586 u8 tos; 1587 u8 buf[HWSIM_PACKETLEN]; 1588 struct ether_header *eth; 1589 struct iphdr *ip; 1590 u8 *dpos; 1591 unsigned int i; 1592 1593 if (hapd->l2_test == NULL) 1594 return -1; 1595 1596 /* format: <dst> <src> <tos> */ 1597 1598 pos = cmd; 1599 used = hwaddr_aton2(pos, dst); 1600 if (used < 0) 1601 return -1; 1602 pos += used; 1603 while (*pos == ' ') 1604 pos++; 1605 used = hwaddr_aton2(pos, src); 1606 if (used < 0) 1607 return -1; 1608 pos += used; 1609 1610 val = strtol(pos, NULL, 0); 1611 if (val < 0 || val > 0xff) 1612 return -1; 1613 tos = val; 1614 1615 eth = (struct ether_header *) buf; 1616 os_memcpy(eth->ether_dhost, dst, ETH_ALEN); 1617 os_memcpy(eth->ether_shost, src, ETH_ALEN); 1618 eth->ether_type = htons(ETHERTYPE_IP); 1619 ip = (struct iphdr *) (eth + 1); 1620 os_memset(ip, 0, sizeof(*ip)); 1621 ip->ihl = 5; 1622 ip->version = 4; 1623 ip->ttl = 64; 1624 ip->tos = tos; 1625 ip->tot_len = htons(HWSIM_IP_LEN); 1626 ip->protocol = 1; 1627 ip->saddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 1); 1628 ip->daddr = htonl(192 << 24 | 168 << 16 | 1 << 8 | 2); 1629 ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); 1630 dpos = (u8 *) (ip + 1); 1631 for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) 1632 *dpos++ = i; 1633 1634 if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, buf, 1635 HWSIM_PACKETLEN) < 0) 1636 return -1; 1637 1638 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR 1639 " src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos); 1640 1641 return 0; 1642} 1643 1644 1645static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd, 1646 char *cmd) 1647{ 1648 u8 *buf; 1649 struct ether_header *eth; 1650 struct l2_packet_data *l2 = NULL; 1651 size_t len; 1652 u16 ethertype; 1653 int res = -1; 1654 const char *ifname = hapd->conf->iface; 1655 1656 if (os_strncmp(cmd, "ifname=", 7) == 0) { 1657 cmd += 7; 1658 ifname = cmd; 1659 cmd = os_strchr(cmd, ' '); 1660 if (cmd == NULL) 1661 return -1; 1662 *cmd++ = '\0'; 1663 } 1664 1665 len = os_strlen(cmd); 1666 if (len & 1 || len < ETH_HLEN * 2) 1667 return -1; 1668 len /= 2; 1669 1670 buf = os_malloc(len); 1671 if (buf == NULL) 1672 return -1; 1673 1674 if (hexstr2bin(cmd, buf, len) < 0) 1675 goto done; 1676 1677 eth = (struct ether_header *) buf; 1678 ethertype = ntohs(eth->ether_type); 1679 1680 l2 = l2_packet_init(ifname, hapd->own_addr, ethertype, 1681 hostapd_data_test_rx, hapd, 1); 1682 if (l2 == NULL) 1683 goto done; 1684 1685 res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len); 1686 wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res); 1687done: 1688 if (l2) 1689 l2_packet_deinit(l2); 1690 os_free(buf); 1691 1692 return res < 0 ? -1 : 0; 1693} 1694 1695#endif /* CONFIG_TESTING_OPTIONS */ 1696 1697 1698static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, 1699 char *pos) 1700{ 1701#ifdef NEED_AP_MLME 1702 struct csa_settings settings; 1703 int ret; 1704 unsigned int i; 1705 1706 ret = hostapd_parse_csa_settings(pos, &settings); 1707 if (ret) 1708 return ret; 1709 1710 for (i = 0; i < iface->num_bss; i++) { 1711 ret = hostapd_switch_channel(iface->bss[i], &settings); 1712 if (ret) { 1713 /* FIX: What do we do if CSA fails in the middle of 1714 * submitting multi-BSS CSA requests? */ 1715 return ret; 1716 } 1717 } 1718 1719 return 0; 1720#else /* NEED_AP_MLME */ 1721 return -1; 1722#endif /* NEED_AP_MLME */ 1723} 1724 1725 1726static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply, 1727 int reply_size, const char *param) 1728{ 1729#ifdef RADIUS_SERVER 1730 if (os_strcmp(param, "radius_server") == 0) { 1731 return radius_server_get_mib(hapd->radius_srv, reply, 1732 reply_size); 1733 } 1734#endif /* RADIUS_SERVER */ 1735 return -1; 1736} 1737 1738 1739static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, 1740 char *buf, size_t buflen) 1741{ 1742 int ret; 1743 char *pos; 1744 u8 *data = NULL; 1745 unsigned int vendor_id, subcmd; 1746 struct wpabuf *reply; 1747 size_t data_len = 0; 1748 1749 /* cmd: <vendor id> <subcommand id> [<hex formatted data>] */ 1750 vendor_id = strtoul(cmd, &pos, 16); 1751 if (!isblank(*pos)) 1752 return -EINVAL; 1753 1754 subcmd = strtoul(pos, &pos, 10); 1755 1756 if (*pos != '\0') { 1757 if (!isblank(*pos++)) 1758 return -EINVAL; 1759 data_len = os_strlen(pos); 1760 } 1761 1762 if (data_len) { 1763 data_len /= 2; 1764 data = os_malloc(data_len); 1765 if (!data) 1766 return -ENOBUFS; 1767 1768 if (hexstr2bin(pos, data, data_len)) { 1769 wpa_printf(MSG_DEBUG, 1770 "Vendor command: wrong parameter format"); 1771 os_free(data); 1772 return -EINVAL; 1773 } 1774 } 1775 1776 reply = wpabuf_alloc((buflen - 1) / 2); 1777 if (!reply) { 1778 os_free(data); 1779 return -ENOBUFS; 1780 } 1781 1782 ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, 1783 reply); 1784 1785 if (ret == 0) 1786 ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), 1787 wpabuf_len(reply)); 1788 1789 wpabuf_free(reply); 1790 os_free(data); 1791 1792 return ret; 1793} 1794 1795 1796static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, 1797 void *sock_ctx) 1798{ 1799 struct hostapd_data *hapd = eloop_ctx; 1800 char buf[4096]; 1801 int res; 1802 struct sockaddr_un from; 1803 socklen_t fromlen = sizeof(from); 1804 char *reply; 1805 const int reply_size = 4096; 1806 int reply_len; 1807 int level = MSG_DEBUG; 1808 1809 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 1810 (struct sockaddr *) &from, &fromlen); 1811 if (res < 0) { 1812 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 1813 strerror(errno)); 1814 return; 1815 } 1816 buf[res] = '\0'; 1817 if (os_strcmp(buf, "PING") == 0) 1818 level = MSG_EXCESSIVE; 1819 wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res); 1820 1821 reply = os_malloc(reply_size); 1822 if (reply == NULL) { 1823 if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, 1824 fromlen) < 0) { 1825 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 1826 strerror(errno)); 1827 } 1828 return; 1829 } 1830 1831 os_memcpy(reply, "OK\n", 3); 1832 reply_len = 3; 1833 1834 if (os_strcmp(buf, "PING") == 0) { 1835 os_memcpy(reply, "PONG\n", 5); 1836 reply_len = 5; 1837 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 1838 if (wpa_debug_reopen_file() < 0) 1839 reply_len = -1; 1840 } else if (os_strcmp(buf, "STATUS") == 0) { 1841 reply_len = hostapd_ctrl_iface_status(hapd, reply, 1842 reply_size); 1843 } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) { 1844 reply_len = hostapd_drv_status(hapd, reply, reply_size); 1845 } else if (os_strcmp(buf, "MIB") == 0) { 1846 reply_len = ieee802_11_get_mib(hapd, reply, reply_size); 1847 if (reply_len >= 0) { 1848 res = wpa_get_mib(hapd->wpa_auth, reply + reply_len, 1849 reply_size - reply_len); 1850 if (res < 0) 1851 reply_len = -1; 1852 else 1853 reply_len += res; 1854 } 1855 if (reply_len >= 0) { 1856 res = ieee802_1x_get_mib(hapd, reply + reply_len, 1857 reply_size - reply_len); 1858 if (res < 0) 1859 reply_len = -1; 1860 else 1861 reply_len += res; 1862 } 1863#ifndef CONFIG_NO_RADIUS 1864 if (reply_len >= 0) { 1865 res = radius_client_get_mib(hapd->radius, 1866 reply + reply_len, 1867 reply_size - reply_len); 1868 if (res < 0) 1869 reply_len = -1; 1870 else 1871 reply_len += res; 1872 } 1873#endif /* CONFIG_NO_RADIUS */ 1874 } else if (os_strncmp(buf, "MIB ", 4) == 0) { 1875 reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size, 1876 buf + 4); 1877 } else if (os_strcmp(buf, "STA-FIRST") == 0) { 1878 reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, 1879 reply_size); 1880 } else if (os_strncmp(buf, "STA ", 4) == 0) { 1881 reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, 1882 reply_size); 1883 } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) { 1884 reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, 1885 reply_size); 1886 } else if (os_strcmp(buf, "ATTACH") == 0) { 1887 if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) 1888 reply_len = -1; 1889 } else if (os_strcmp(buf, "DETACH") == 0) { 1890 if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) 1891 reply_len = -1; 1892 } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { 1893 if (hostapd_ctrl_iface_level(hapd, &from, fromlen, 1894 buf + 6)) 1895 reply_len = -1; 1896 } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { 1897 if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) 1898 reply_len = -1; 1899 } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { 1900 if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) 1901 reply_len = -1; 1902 } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { 1903 if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) 1904 reply_len = -1; 1905#ifdef CONFIG_IEEE80211W 1906#ifdef NEED_AP_MLME 1907 } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { 1908 if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) 1909 reply_len = -1; 1910#endif /* NEED_AP_MLME */ 1911#endif /* CONFIG_IEEE80211W */ 1912#ifdef CONFIG_WPS 1913 } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { 1914 if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) 1915 reply_len = -1; 1916 } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { 1917 reply_len = hostapd_ctrl_iface_wps_check_pin( 1918 hapd, buf + 14, reply, reply_size); 1919 } else if (os_strcmp(buf, "WPS_PBC") == 0) { 1920 if (hostapd_wps_button_pushed(hapd, NULL)) 1921 reply_len = -1; 1922 } else if (os_strcmp(buf, "WPS_CANCEL") == 0) { 1923 if (hostapd_wps_cancel(hapd)) 1924 reply_len = -1; 1925 } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { 1926 reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, 1927 reply, reply_size); 1928 } else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) { 1929 if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0) 1930 reply_len = -1; 1931 } else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) { 1932 reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply, 1933 reply_size); 1934#ifdef CONFIG_WPS_NFC 1935 } else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) { 1936 if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17)) 1937 reply_len = -1; 1938 } else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) { 1939 reply_len = hostapd_ctrl_iface_wps_nfc_config_token( 1940 hapd, buf + 21, reply, reply_size); 1941 } else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) { 1942 reply_len = hostapd_ctrl_iface_wps_nfc_token( 1943 hapd, buf + 14, reply, reply_size); 1944 } else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) { 1945 reply_len = hostapd_ctrl_iface_nfc_get_handover_sel( 1946 hapd, buf + 21, reply, reply_size); 1947 } else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) { 1948 if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20)) 1949 reply_len = -1; 1950#endif /* CONFIG_WPS_NFC */ 1951#endif /* CONFIG_WPS */ 1952#ifdef CONFIG_INTERWORKING 1953 } else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) { 1954 if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16)) 1955 reply_len = -1; 1956 } else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) { 1957 if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18)) 1958 reply_len = -1; 1959#endif /* CONFIG_INTERWORKING */ 1960#ifdef CONFIG_HS20 1961 } else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) { 1962 if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15)) 1963 reply_len = -1; 1964 } else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) { 1965 if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16)) 1966 reply_len = -1; 1967#endif /* CONFIG_HS20 */ 1968#ifdef CONFIG_WNM 1969 } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) { 1970 if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18)) 1971 reply_len = -1; 1972 } else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) { 1973 if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13)) 1974 reply_len = -1; 1975 } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) { 1976 if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11)) 1977 reply_len = -1; 1978#endif /* CONFIG_WNM */ 1979 } else if (os_strcmp(buf, "GET_CONFIG") == 0) { 1980 reply_len = hostapd_ctrl_iface_get_config(hapd, reply, 1981 reply_size); 1982 } else if (os_strncmp(buf, "SET ", 4) == 0) { 1983 if (hostapd_ctrl_iface_set(hapd, buf + 4)) 1984 reply_len = -1; 1985 } else if (os_strncmp(buf, "GET ", 4) == 0) { 1986 reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply, 1987 reply_size); 1988 } else if (os_strncmp(buf, "ENABLE", 6) == 0) { 1989 if (hostapd_ctrl_iface_enable(hapd->iface)) 1990 reply_len = -1; 1991 } else if (os_strncmp(buf, "RELOAD", 6) == 0) { 1992 if (hostapd_ctrl_iface_reload(hapd->iface)) 1993 reply_len = -1; 1994 } else if (os_strncmp(buf, "DISABLE", 7) == 0) { 1995 if (hostapd_ctrl_iface_disable(hapd->iface)) 1996 reply_len = -1; 1997#ifdef CONFIG_TESTING_OPTIONS 1998 } else if (os_strncmp(buf, "RADAR ", 6) == 0) { 1999 if (hostapd_ctrl_iface_radar(hapd, buf + 6)) 2000 reply_len = -1; 2001 } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) { 2002 if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8)) 2003 reply_len = -1; 2004 } else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) { 2005 if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0) 2006 reply_len = -1; 2007 } else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) { 2008 if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0) 2009 reply_len = -1; 2010 } else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) { 2011 if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0) 2012 reply_len = -1; 2013 } else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) { 2014 if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0) 2015 reply_len = -1; 2016#endif /* CONFIG_TESTING_OPTIONS */ 2017 } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) { 2018 if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12)) 2019 reply_len = -1; 2020 } else if (os_strncmp(buf, "VENDOR ", 7) == 0) { 2021 reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply, 2022 reply_size); 2023 } else if (os_strcmp(buf, "ERP_FLUSH") == 0) { 2024 ieee802_1x_erp_flush(hapd); 2025#ifdef RADIUS_SERVER 2026 radius_server_erp_flush(hapd->radius_srv); 2027#endif /* RADIUS_SERVER */ 2028 } else { 2029 os_memcpy(reply, "UNKNOWN COMMAND\n", 16); 2030 reply_len = 16; 2031 } 2032 2033 if (reply_len < 0) { 2034 os_memcpy(reply, "FAIL\n", 5); 2035 reply_len = 5; 2036 } 2037 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 2038 fromlen) < 0) { 2039 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2040 strerror(errno)); 2041 } 2042 os_free(reply); 2043} 2044 2045 2046static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd) 2047{ 2048 char *buf; 2049 size_t len; 2050 2051 if (hapd->conf->ctrl_interface == NULL) 2052 return NULL; 2053 2054 len = os_strlen(hapd->conf->ctrl_interface) + 2055 os_strlen(hapd->conf->iface) + 2; 2056 buf = os_malloc(len); 2057 if (buf == NULL) 2058 return NULL; 2059 2060 os_snprintf(buf, len, "%s/%s", 2061 hapd->conf->ctrl_interface, hapd->conf->iface); 2062 buf[len - 1] = '\0'; 2063 return buf; 2064} 2065 2066 2067static void hostapd_ctrl_iface_msg_cb(void *ctx, int level, int global, 2068 const char *txt, size_t len) 2069{ 2070 struct hostapd_data *hapd = ctx; 2071 if (hapd == NULL) 2072 return; 2073 hostapd_ctrl_iface_send(hapd, level, txt, len); 2074} 2075 2076 2077int hostapd_ctrl_iface_init(struct hostapd_data *hapd) 2078{ 2079 struct sockaddr_un addr; 2080 int s = -1; 2081 char *fname = NULL; 2082 2083 if (hapd->ctrl_sock > -1) { 2084 wpa_printf(MSG_DEBUG, "ctrl_iface already exists!"); 2085 return 0; 2086 } 2087 2088 if (hapd->conf->ctrl_interface == NULL) 2089 return 0; 2090 2091 if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2092 if (errno == EEXIST) { 2093 wpa_printf(MSG_DEBUG, "Using existing control " 2094 "interface directory."); 2095 } else { 2096 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 2097 strerror(errno)); 2098 goto fail; 2099 } 2100 } 2101 2102 if (hapd->conf->ctrl_interface_gid_set && 2103 chown(hapd->conf->ctrl_interface, -1, 2104 hapd->conf->ctrl_interface_gid) < 0) { 2105 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2106 strerror(errno)); 2107 return -1; 2108 } 2109 2110 if (!hapd->conf->ctrl_interface_gid_set && 2111 hapd->iface->interfaces->ctrl_iface_group && 2112 chown(hapd->conf->ctrl_interface, -1, 2113 hapd->iface->interfaces->ctrl_iface_group) < 0) { 2114 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2115 strerror(errno)); 2116 return -1; 2117 } 2118 2119#ifdef ANDROID 2120 /* 2121 * Android is using umask 0077 which would leave the control interface 2122 * directory without group access. This breaks things since Wi-Fi 2123 * framework assumes that this directory can be accessed by other 2124 * applications in the wifi group. Fix this by adding group access even 2125 * if umask value would prevent this. 2126 */ 2127 if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { 2128 wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s", 2129 strerror(errno)); 2130 /* Try to continue anyway */ 2131 } 2132#endif /* ANDROID */ 2133 2134 if (os_strlen(hapd->conf->ctrl_interface) + 1 + 2135 os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path)) 2136 goto fail; 2137 2138 s = socket(PF_UNIX, SOCK_DGRAM, 0); 2139 if (s < 0) { 2140 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 2141 goto fail; 2142 } 2143 2144 os_memset(&addr, 0, sizeof(addr)); 2145#ifdef __FreeBSD__ 2146 addr.sun_len = sizeof(addr); 2147#endif /* __FreeBSD__ */ 2148 addr.sun_family = AF_UNIX; 2149 fname = hostapd_ctrl_iface_path(hapd); 2150 if (fname == NULL) 2151 goto fail; 2152 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 2153 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2154 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 2155 strerror(errno)); 2156 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2157 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 2158 " allow connections - assuming it was left" 2159 "over from forced program termination"); 2160 if (unlink(fname) < 0) { 2161 wpa_printf(MSG_ERROR, 2162 "Could not unlink existing ctrl_iface socket '%s': %s", 2163 fname, strerror(errno)); 2164 goto fail; 2165 } 2166 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 2167 0) { 2168 wpa_printf(MSG_ERROR, 2169 "hostapd-ctrl-iface: bind(PF_UNIX): %s", 2170 strerror(errno)); 2171 goto fail; 2172 } 2173 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 2174 "ctrl_iface socket '%s'", fname); 2175 } else { 2176 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 2177 "be in use - cannot override it"); 2178 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 2179 "not used anymore", fname); 2180 os_free(fname); 2181 fname = NULL; 2182 goto fail; 2183 } 2184 } 2185 2186 if (hapd->conf->ctrl_interface_gid_set && 2187 chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) { 2188 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 2189 strerror(errno)); 2190 goto fail; 2191 } 2192 2193 if (!hapd->conf->ctrl_interface_gid_set && 2194 hapd->iface->interfaces->ctrl_iface_group && 2195 chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) { 2196 wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s", 2197 strerror(errno)); 2198 goto fail; 2199 } 2200 2201 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 2202 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 2203 strerror(errno)); 2204 goto fail; 2205 } 2206 os_free(fname); 2207 2208 hapd->ctrl_sock = s; 2209 eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, 2210 NULL); 2211 hapd->msg_ctx = hapd; 2212 wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); 2213 2214 return 0; 2215 2216fail: 2217 if (s >= 0) 2218 close(s); 2219 if (fname) { 2220 unlink(fname); 2221 os_free(fname); 2222 } 2223 return -1; 2224} 2225 2226 2227void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) 2228{ 2229 struct wpa_ctrl_dst *dst, *prev; 2230 2231 if (hapd->ctrl_sock > -1) { 2232 char *fname; 2233 eloop_unregister_read_sock(hapd->ctrl_sock); 2234 close(hapd->ctrl_sock); 2235 hapd->ctrl_sock = -1; 2236 fname = hostapd_ctrl_iface_path(hapd); 2237 if (fname) 2238 unlink(fname); 2239 os_free(fname); 2240 2241 if (hapd->conf->ctrl_interface && 2242 rmdir(hapd->conf->ctrl_interface) < 0) { 2243 if (errno == ENOTEMPTY) { 2244 wpa_printf(MSG_DEBUG, "Control interface " 2245 "directory not empty - leaving it " 2246 "behind"); 2247 } else { 2248 wpa_printf(MSG_ERROR, 2249 "rmdir[ctrl_interface=%s]: %s", 2250 hapd->conf->ctrl_interface, 2251 strerror(errno)); 2252 } 2253 } 2254 } 2255 2256 dst = hapd->ctrl_dst; 2257 while (dst) { 2258 prev = dst; 2259 dst = dst->next; 2260 os_free(prev); 2261 } 2262 2263#ifdef CONFIG_TESTING_OPTIONS 2264 l2_packet_deinit(hapd->l2_test); 2265 hapd->l2_test = NULL; 2266#endif /* CONFIG_TESTING_OPTIONS */ 2267} 2268 2269 2270static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces, 2271 char *buf) 2272{ 2273 if (hostapd_add_iface(interfaces, buf) < 0) { 2274 wpa_printf(MSG_ERROR, "Adding interface %s failed", buf); 2275 return -1; 2276 } 2277 return 0; 2278} 2279 2280 2281static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces, 2282 char *buf) 2283{ 2284 if (hostapd_remove_iface(interfaces, buf) < 0) { 2285 wpa_printf(MSG_ERROR, "Removing interface %s failed", buf); 2286 return -1; 2287 } 2288 return 0; 2289} 2290 2291 2292static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) 2293{ 2294#ifdef CONFIG_WPS_TESTING 2295 wps_version_number = 0x20; 2296 wps_testing_dummy_cred = 0; 2297 wps_corrupt_pkhash = 0; 2298#endif /* CONFIG_WPS_TESTING */ 2299} 2300 2301 2302static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, 2303 void *sock_ctx) 2304{ 2305 void *interfaces = eloop_ctx; 2306 char buf[256]; 2307 int res; 2308 struct sockaddr_un from; 2309 socklen_t fromlen = sizeof(from); 2310 char reply[24]; 2311 int reply_len; 2312 2313 res = recvfrom(sock, buf, sizeof(buf) - 1, 0, 2314 (struct sockaddr *) &from, &fromlen); 2315 if (res < 0) { 2316 wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", 2317 strerror(errno)); 2318 return; 2319 } 2320 buf[res] = '\0'; 2321 wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf); 2322 2323 os_memcpy(reply, "OK\n", 3); 2324 reply_len = 3; 2325 2326 if (os_strcmp(buf, "PING") == 0) { 2327 os_memcpy(reply, "PONG\n", 5); 2328 reply_len = 5; 2329 } else if (os_strncmp(buf, "RELOG", 5) == 0) { 2330 if (wpa_debug_reopen_file() < 0) 2331 reply_len = -1; 2332 } else if (os_strcmp(buf, "FLUSH") == 0) { 2333 hostapd_ctrl_iface_flush(interfaces); 2334 } else if (os_strncmp(buf, "ADD ", 4) == 0) { 2335 if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0) 2336 reply_len = -1; 2337 } else if (os_strncmp(buf, "REMOVE ", 7) == 0) { 2338 if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0) 2339 reply_len = -1; 2340#ifdef CONFIG_MODULE_TESTS 2341 } else if (os_strcmp(buf, "MODULE_TESTS") == 0) { 2342 int hapd_module_tests(void); 2343 if (hapd_module_tests() < 0) 2344 reply_len = -1; 2345#endif /* CONFIG_MODULE_TESTS */ 2346 } else { 2347 wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command " 2348 "ignored"); 2349 reply_len = -1; 2350 } 2351 2352 if (reply_len < 0) { 2353 os_memcpy(reply, "FAIL\n", 5); 2354 reply_len = 5; 2355 } 2356 2357 if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, 2358 fromlen) < 0) { 2359 wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s", 2360 strerror(errno)); 2361 } 2362} 2363 2364 2365static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface) 2366{ 2367 char *buf; 2368 size_t len; 2369 2370 if (interface->global_iface_path == NULL) 2371 return NULL; 2372 2373 len = os_strlen(interface->global_iface_path) + 2374 os_strlen(interface->global_iface_name) + 2; 2375 buf = os_malloc(len); 2376 if (buf == NULL) 2377 return NULL; 2378 2379 os_snprintf(buf, len, "%s/%s", interface->global_iface_path, 2380 interface->global_iface_name); 2381 buf[len - 1] = '\0'; 2382 return buf; 2383} 2384 2385 2386int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) 2387{ 2388 struct sockaddr_un addr; 2389 int s = -1; 2390 char *fname = NULL; 2391 2392 if (interface->global_iface_path == NULL) { 2393 wpa_printf(MSG_DEBUG, "ctrl_iface not configured!"); 2394 return 0; 2395 } 2396 2397 if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) { 2398 if (errno == EEXIST) { 2399 wpa_printf(MSG_DEBUG, "Using existing control " 2400 "interface directory."); 2401 } else { 2402 wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s", 2403 strerror(errno)); 2404 goto fail; 2405 } 2406 } else if (interface->ctrl_iface_group && 2407 chown(interface->global_iface_path, -1, 2408 interface->ctrl_iface_group) < 0) { 2409 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2410 strerror(errno)); 2411 goto fail; 2412 } 2413 2414 if (os_strlen(interface->global_iface_path) + 1 + 2415 os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path)) 2416 goto fail; 2417 2418 s = socket(PF_UNIX, SOCK_DGRAM, 0); 2419 if (s < 0) { 2420 wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno)); 2421 goto fail; 2422 } 2423 2424 os_memset(&addr, 0, sizeof(addr)); 2425#ifdef __FreeBSD__ 2426 addr.sun_len = sizeof(addr); 2427#endif /* __FreeBSD__ */ 2428 addr.sun_family = AF_UNIX; 2429 fname = hostapd_global_ctrl_iface_path(interface); 2430 if (fname == NULL) 2431 goto fail; 2432 os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path)); 2433 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2434 wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", 2435 strerror(errno)); 2436 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 2437 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" 2438 " allow connections - assuming it was left" 2439 "over from forced program termination"); 2440 if (unlink(fname) < 0) { 2441 wpa_printf(MSG_ERROR, 2442 "Could not unlink existing ctrl_iface socket '%s': %s", 2443 fname, strerror(errno)); 2444 goto fail; 2445 } 2446 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 2447 0) { 2448 wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s", 2449 strerror(errno)); 2450 goto fail; 2451 } 2452 wpa_printf(MSG_DEBUG, "Successfully replaced leftover " 2453 "ctrl_iface socket '%s'", fname); 2454 } else { 2455 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " 2456 "be in use - cannot override it"); 2457 wpa_printf(MSG_INFO, "Delete '%s' manually if it is " 2458 "not used anymore", fname); 2459 os_free(fname); 2460 fname = NULL; 2461 goto fail; 2462 } 2463 } 2464 2465 if (interface->ctrl_iface_group && 2466 chown(fname, -1, interface->ctrl_iface_group) < 0) { 2467 wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s", 2468 strerror(errno)); 2469 goto fail; 2470 } 2471 2472 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { 2473 wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s", 2474 strerror(errno)); 2475 goto fail; 2476 } 2477 os_free(fname); 2478 2479 interface->global_ctrl_sock = s; 2480 eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive, 2481 interface, NULL); 2482 2483 return 0; 2484 2485fail: 2486 if (s >= 0) 2487 close(s); 2488 if (fname) { 2489 unlink(fname); 2490 os_free(fname); 2491 } 2492 return -1; 2493} 2494 2495 2496void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces) 2497{ 2498 char *fname = NULL; 2499 2500 if (interfaces->global_ctrl_sock > -1) { 2501 eloop_unregister_read_sock(interfaces->global_ctrl_sock); 2502 close(interfaces->global_ctrl_sock); 2503 interfaces->global_ctrl_sock = -1; 2504 fname = hostapd_global_ctrl_iface_path(interfaces); 2505 if (fname) { 2506 unlink(fname); 2507 os_free(fname); 2508 } 2509 2510 if (interfaces->global_iface_path && 2511 rmdir(interfaces->global_iface_path) < 0) { 2512 if (errno == ENOTEMPTY) { 2513 wpa_printf(MSG_DEBUG, "Control interface " 2514 "directory not empty - leaving it " 2515 "behind"); 2516 } else { 2517 wpa_printf(MSG_ERROR, 2518 "rmdir[ctrl_interface=%s]: %s", 2519 interfaces->global_iface_path, 2520 strerror(errno)); 2521 } 2522 } 2523 os_free(interfaces->global_iface_path); 2524 interfaces->global_iface_path = NULL; 2525 } 2526} 2527 2528 2529static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, 2530 const char *buf, size_t len) 2531{ 2532 struct wpa_ctrl_dst *dst, *next; 2533 struct msghdr msg; 2534 int idx; 2535 struct iovec io[2]; 2536 char levelstr[10]; 2537 2538 dst = hapd->ctrl_dst; 2539 if (hapd->ctrl_sock < 0 || dst == NULL) 2540 return; 2541 2542 os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); 2543 io[0].iov_base = levelstr; 2544 io[0].iov_len = os_strlen(levelstr); 2545 io[1].iov_base = (char *) buf; 2546 io[1].iov_len = len; 2547 os_memset(&msg, 0, sizeof(msg)); 2548 msg.msg_iov = io; 2549 msg.msg_iovlen = 2; 2550 2551 idx = 0; 2552 while (dst) { 2553 next = dst->next; 2554 if (level >= dst->debug_level) { 2555 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", 2556 (u8 *) dst->addr.sun_path, dst->addrlen - 2557 offsetof(struct sockaddr_un, sun_path)); 2558 msg.msg_name = &dst->addr; 2559 msg.msg_namelen = dst->addrlen; 2560 if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { 2561 int _errno = errno; 2562 wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: " 2563 "%d - %s", 2564 idx, errno, strerror(errno)); 2565 dst->errors++; 2566 if (dst->errors > 10 || _errno == ENOENT) { 2567 hostapd_ctrl_iface_detach( 2568 hapd, &dst->addr, 2569 dst->addrlen); 2570 } 2571 } else 2572 dst->errors = 0; 2573 } 2574 idx++; 2575 dst = next; 2576 } 2577} 2578 2579#endif /* CONFIG_NATIVE_WINDOWS */ 2580